2012-11-12 21:36:27

by Arvid Brodin

[permalink] [raw]
Subject: [PATCH] fs/proc: Add process text segment md5-summing

Adds /proc/<pid>/text_md5sum which, when read, calculates an md5sum over
the process' text segment. This can detect some cases where the system RAM
has been disturbed by e.g. ESD or cosmic radiation (on systems where ECC
is not available). It might also detect some accidental or malicious
modifications of executables, where the perpetrator has not bothered to
cover up the tracks.

Signed-off-by: Arvid Brodin <[email protected]>
---

I'm not sure which tree this should go into. I made this patch against
next-20121112.

I had some questions and posted this patch before to get them answered. See
http://www.spinics.net/lists/kernel/msg1428503.html for the comments I
received and my responses.

Changes since the post linked above:

* Fixed possible (probable!) crash due to not using get_task_mm()
to lock task->mm.
* Changed help text to clarify that this is not a security patch.
Thanks goes to the people commenting about this!

fs/proc/Kconfig | 14 +++++++
fs/proc/base.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 0 deletions(-)

diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
index 15af622..97fe118 100644
--- a/fs/proc/Kconfig
+++ b/fs/proc/Kconfig
@@ -67,3 +67,17 @@ config PROC_PAGE_MONITOR
/proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
/proc/kpagecount, and /proc/kpageflags. Disabling these
interfaces will reduce the size of the kernel by approximately 4kb.
+
+config PROC_TEXT_MD5SUM
+ bool "/proc/<pid>/text_md5sum support"
+ depends on PROC_FS
+ select CRYPTO
+ select CRYPTO_MD5
+ help
+ Read /proc/<pid>/text_md5sum to get the kernel to perform an MD5
+ checksum over the process' text segment and print the result. This
+ can detect some cases where the system RAM has been disturbed by
+ e.g. ESD or cosmic radiation (on systems where ECC is not available).
+ It might also detect some accidental or malicious modifications of
+ executables, where the perpetrator has not bothered to cover up the
+ tracks.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b268bdf..b9c5fda 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -85,6 +85,10 @@
#include <linux/fs_struct.h>
#include <linux/slab.h>
#include <linux/flex_array.h>
+#ifdef CONFIG_PROC_TEXT_MD5SUM
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#endif
#ifdef CONFIG_HARDWALL
#include <asm/hardwall.h>
#endif
@@ -2526,6 +2530,111 @@ static int proc_pid_personality(struct seq_file *m, struct
pid_namespace *ns,
return err;
}

+#ifdef CONFIG_PROC_TEXT_MD5SUM
+#define MD5_DIGEST_SIZE 16
+static int proc_get_text_md5sum(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
+{
+ int retval;
+ int text_size;
+ int nr_pages, nr_pages_mapped;
+ int i;
+ struct mm_struct *mm;
+ struct page **pages;
+ struct scatterlist *sgl, *sg;
+ u8 result[MD5_DIGEST_SIZE + 2];
+ struct crypto_hash *tfm;
+ struct hash_desc desc;
+
+ retval = 0;
+
+ mm = get_task_mm(task);
+ if (!mm)
+ return -EINVAL;
+
+ text_size = mm->end_code - mm->start_code;
+ nr_pages = (text_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+
+ /**** User page code ****/
+
+ pages = kmalloc(nr_pages * sizeof(*pages), GFP_KERNEL);
+ if (!pages) {
+ retval = -ENOMEM;
+ goto err_pages;
+ }
+
+ down_read(&mm->mmap_sem);
+ nr_pages_mapped = get_user_pages(current, mm,
+ mm->start_code, nr_pages, 0, 0, pages, NULL);
+ up_read(&mm->mmap_sem);
+ if (nr_pages_mapped < 0) {
+ retval = nr_pages_mapped;
+ goto err_mapped;
+ }
+ if (nr_pages_mapped < nr_pages) {
+ retval = -EBUSY; /* Weird error code for this,
+ but couldn't find any better */
+ goto err_not_all_pages;
+ }
+
+
+ /**** Scatterlist code ****/
+
+ sgl = kmalloc(nr_pages_mapped * sizeof(*sgl), GFP_KERNEL);
+ if (!sgl) {
+ retval = -ENOMEM;
+ goto err_sg;
+ }
+
+ sg_init_table(sgl, nr_pages_mapped);
+ for_each_sg(sgl, sg, nr_pages_mapped, i)
+ sg_set_page(sg, pages[i], (i < nr_pages_mapped) ? PAGE_SIZE :
+ text_size & ~PAGE_MASK, 0);
+
+
+ /**** Crypto code ****/
+
+ tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm)) {
+ retval = -ENOMEM;
+ goto err_crypto;
+ }
+
+ desc.tfm = tfm;
+ desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ memset(result, 0, MD5_DIGEST_SIZE + 2);
+ retval = crypto_hash_digest(&desc, sgl, text_size, result);
+ if (retval)
+ goto err_digest;
+
+ for (i = 0; i < MD5_DIGEST_SIZE; i++)
+ seq_printf(m, "%02x", result[i]);
+ seq_printf(m, "\n");
+
+
+err_digest:
+ crypto_free_hash(tfm);
+
+err_crypto:
+ kfree(sgl);
+
+err_sg:
+err_not_all_pages:
+ for (i = 0; i < nr_pages_mapped; i++)
+ put_page(pages[i]);
+
+err_mapped:
+ kfree(pages);
+
+err_pages:
+ mmput(mm);
+
+ return retval;
+}
+#endif /* CONFIG_PROC_TEXT_MD5SUM */
+
/*
* Thread groups
*/
@@ -2621,6 +2730,9 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
#endif
+#ifdef CONFIG_PROC_TEXT_MD5SUM
+ ONE("text_md5sum", S_IRUGO, proc_get_text_md5sum),
+#endif
};

static int proc_tgid_base_readdir(struct file * filp,
--
1.7.3.4


--
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?


2012-11-12 23:03:28

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] fs/proc: Add process text segment md5-summing

On Mon, 12 Nov 2012 21:36:17 +0000
Arvid Brodin <[email protected]> wrote:

> Adds /proc/<pid>/text_md5sum which, when read, calculates an md5sum over
> the process' text segment. This can detect some cases where the system RAM
> has been disturbed by e.g. ESD or cosmic radiation (on systems where ECC
> is not available). It might also detect some accidental or malicious
> modifications of executables, where the perpetrator has not bothered to
> cover up the tracks.

I thought the review comments regarding the earlier patch were rather
fatal, sorry.

> + Read /proc/<pid>/text_md5sum to get the kernel to perform an MD5
> + checksum over the process' text segment and print the result. This
> + can detect some cases where the system RAM has been disturbed by
> + e.g. ESD or cosmic radiation (on systems where ECC is not available).
> + It might also detect some accidental or malicious modifications of
> + executables, where the perpetrator has not bothered to cover up the
> + tracks.

And that doesn't seem to help much, really. .text is only a small part
of a process's VM and corruption of data, bss, heap or stack is just as
bad.

2012-11-13 02:16:16

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH] fs/proc: Add process text segment md5-summing

Andrew Morton <[email protected]> writes:

> On Mon, 12 Nov 2012 21:36:17 +0000
> Arvid Brodin <[email protected]> wrote:
>
>> Adds /proc/<pid>/text_md5sum which, when read, calculates an md5sum over
>> the process' text segment. This can detect some cases where the system RAM
>> has been disturbed by e.g. ESD or cosmic radiation (on systems where ECC
>> is not available). It might also detect some accidental or malicious
>> modifications of executables, where the perpetrator has not bothered to
>> cover up the tracks.
>
> I thought the review comments regarding the earlier patch were rather
> fatal, sorry.

To add another nail in the coffin.

You can do this with ptrace or with /proc/<pid>/mem without a kernel
patch.

To make this safe would need a ptrace_may_acces(PTRACE_MODE_READ)
permission check. At which point not doing this with ptrace just adds
up to extra kernel maintenance for no real point.

Eric

2012-11-14 00:11:06

by Arvid Brodin

[permalink] [raw]
Subject: Re: [PATCH] fs/proc: Add process text segment md5-summing

On 2012-11-13 00:03, Andrew Morton wrote:
> On Mon, 12 Nov 2012 21:36:17 +0000
> Arvid Brodin <[email protected]> wrote:
>
>> Adds /proc/<pid>/text_md5sum which, when read, calculates an md5sum over
>> the process' text segment. This can detect some cases where the system RAM
>> has been disturbed by e.g. ESD or cosmic radiation (on systems where ECC
>> is not available). It might also detect some accidental or malicious
>> modifications of executables, where the perpetrator has not bothered to
>> cover up the tracks.
>
> I thought the review comments regarding the earlier patch were rather
> fatal, sorry.

Ok. I get the point now at least. :) Thanks for taking the time to comment
on this!

--
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarn?sgatan 7 | SE-164 40 Kista | Sweden | xdin.com-

2012-11-14 01:45:48

by Arvid Brodin

[permalink] [raw]
Subject: Re: [PATCH] fs/proc: Add process text segment md5-summing

On 2012-11-13 03:16, Eric W. Biederman wrote:
> To add another nail in the coffin.
>
> You can do this with ptrace or with /proc/<pid>/mem without a kernel
> patch.
>
> To make this safe would need a ptrace_may_acces(PTRACE_MODE_READ)
> permission check. At which point not doing this with ptrace just adds
> up to extra kernel maintenance for no real point.

If my client still wants to run text segment checks, even after the
criticism of the idea behind the patch, the above should prove very
handy. Thanks!


--
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?