2013-08-22 11:01:54

by Lee, Chun-Yi

[permalink] [raw]
Subject: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

In current solution, the snapshot signature check used the RSA key-pair
that are generated by bootloader(e.g. shim) and pass the key-pair to
kernel through EFI variables. I choice to binding the snapshot
signature check mechanism with UEFI secure boot for provide stronger
protection of hibernate. Current behavior is following:

+ UEFI Secure Boot ON, Kernel found key-pair from shim:
Will do the S4 signature check.

+ UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
Will lock down S4 function.

+ UEFI Secure Boot OFF
Will NOT do the S4 signature check.
Ignore any keys from bootloader.

v2:
Replace sign_key_data_loaded() by skey_data_available() to check sign key data
is available for hibernate.

Reviewed-by: Jiri Kosina <[email protected]>
Signed-off-by: Lee, Chun-Yi <jlee-IBi9RG/[email protected]>
---
kernel/power/hibernate.c | 36 +++++++++++++++++-
kernel/power/main.c | 11 +++++-
kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
kernel/power/swap.c | 4 +-
kernel/power/user.c | 11 +++++
5 files changed, 112 insertions(+), 45 deletions(-)

diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index c545b15..0f19f3d 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -29,6 +29,7 @@
#include <linux/ctype.h>
#include <linux/genhd.h>
#include <linux/key.h>
+#include <linux/efi.h>

#include "power.h"

@@ -632,7 +633,14 @@ static void power_down(void)
int hibernate(void)
{
int error;
- int skey_error;
+
+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
+#else
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+#endif
+ return -EPERM;
+ }

lock_system_sleep();
/* The snapshot device should not be opened while we're running */
@@ -799,6 +807,15 @@ static int software_resume(void)
if (error)
goto Unlock;

+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
+#else
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+#endif
+ mutex_unlock(&pm_mutex);
+ return -EPERM;
+ }
+
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
error = -EBUSY;
@@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
int i;
char *start = buf;

+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
+#else
+ if (efi_enabled(EFI_SECURE_BOOT)) {
+#endif
+ buf += sprintf(buf, "[%s]\n", "disabled");
+ return buf-start;
+ }
+
for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
if (!hibernation_modes[i])
continue;
@@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
char *p;
int mode = HIBERNATION_INVALID;

+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
+#else
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+#endif
+ return -EPERM;
+ }
+
p = memchr(buf, '\n', n);
len = p ? p - buf : n;

diff --git a/kernel/power/main.c b/kernel/power/main.c
index 1d1bf63..47bf300 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -15,6 +15,7 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/efi.h>

#include "power.h"

@@ -301,7 +302,15 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
}
#endif
#ifdef CONFIG_HIBERNATION
- s += sprintf(s, "%s\n", "disk");
+ if (!efi_enabled(EFI_SECURE_BOOT)) {
+ s += sprintf(s, "%s\n", "disk");
+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ } else if (skey_data_available()) {
+ s += sprintf(s, "%s\n", "disk");
+#endif
+ } else {
+ s += sprintf(s, "\n");
+ }
#else
if (s != buf)
/* convert the last space to a newline */
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index cf3d69c..36c7157 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -860,7 +860,8 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn)

BUG_ON(!PageHighMem(page));

- if (swsusp_page_is_sign_key(page))
+ if (!capable(CAP_COMPROMISE_KERNEL) &&
+ swsusp_page_is_sign_key(page))
return NULL;

if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page) ||
@@ -925,7 +926,8 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn)

BUG_ON(PageHighMem(page));

- if (swsusp_page_is_sign_key(page))
+ if (!capable(CAP_COMPROMISE_KERNEL) &&
+ swsusp_page_is_sign_key(page))
return NULL;

if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
@@ -1056,35 +1058,37 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
#ifdef CONFIG_SNAPSHOT_VERIFICATION
struct page *d_page;
void *hash_buffer = NULL;
- struct crypto_shash *tfm;
- struct shash_desc *desc;
- u8 *digest;
+ struct crypto_shash *tfm = NULL;
+ struct shash_desc *desc = NULL;
+ u8 *digest = NULL;
size_t digest_size, desc_size;
struct key *s4_sign_key;
struct public_key_signature *pks;
int ret;

ret = -ENOMEM;
- tfm = crypto_alloc_shash(SNAPSHOT_HASH, 0, 0);
- if (IS_ERR(tfm)) {
- pr_err("IS_ERR(tfm): %ld", PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+ tfm = crypto_alloc_shash(SNAPSHOT_HASH, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_err("IS_ERR(tfm): %ld", PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }

- desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
- digest_size = crypto_shash_digestsize(tfm);
- digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
- if (!digest) {
- pr_err("digest allocate fail");
- ret = -ENOMEM;
- goto error_digest;
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ digest_size = crypto_shash_digestsize(tfm);
+ digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
+ if (!digest) {
+ pr_err("digest allocate fail");
+ ret = -ENOMEM;
+ goto error_digest;
+ }
+ desc = (void *) digest + digest_size;
+ desc->tfm = tfm;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ ret = crypto_shash_init(desc);
+ if (ret < 0)
+ goto error_shash;
}
- desc = (void *) digest + digest_size;
- desc->tfm = tfm;
- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
- ret = crypto_shash_init(desc);
- if (ret < 0)
- goto error_shash;
#endif /* CONFIG_SNAPSHOT_VERIFICATION */

for_each_populated_zone(zone) {
@@ -1106,24 +1110,29 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
copy_data_page(dst_pfn, pfn);

#ifdef CONFIG_SNAPSHOT_VERIFICATION
- /* Generate digest */
- d_page = pfn_to_page(dst_pfn);
- if (PageHighMem(d_page)) {
- void *kaddr;
- kaddr = kmap_atomic(d_page);
- copy_page(buffer, kaddr);
- kunmap_atomic(kaddr);
- hash_buffer = buffer;
- } else {
- hash_buffer = page_address(d_page);
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+ /* Generate digest */
+ d_page = pfn_to_page(dst_pfn);
+ if (PageHighMem(d_page)) {
+ void *kaddr;
+ kaddr = kmap_atomic(d_page);
+ copy_page(buffer, kaddr);
+ kunmap_atomic(kaddr);
+ hash_buffer = buffer;
+ } else {
+ hash_buffer = page_address(d_page);
+ }
+ ret = crypto_shash_update(desc, hash_buffer, PAGE_SIZE);
+ if (ret)
+ goto error_shash;
}
- ret = crypto_shash_update(desc, hash_buffer, PAGE_SIZE);
- if (ret)
- goto error_shash;
#endif
}

#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (capable(CAP_COMPROMISE_KERNEL))
+ goto skip_sign;
+
crypto_shash_final(desc, digest);
if (ret)
goto error_shash;
@@ -1153,6 +1162,8 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
kfree(pks);
kfree(digest);
crypto_free_shash(tfm);
+
+skip_sign:
#endif /* CONFIG_SNAPSHOT_VERIFICATION */

return 0;
@@ -2382,9 +2393,11 @@ int snapshot_write_next(struct snapshot_handle *handle)
/* Allocate void * array to keep buffer point for generate hash,
* h_buf will freed in snapshot_image_verify().
*/
- h_buf = kmalloc(sizeof(void *) * nr_copy_pages, GFP_KERNEL);
- if (!h_buf)
- pr_err("Allocate hash buffer fail!");
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+ h_buf = kmalloc(sizeof(void *) * nr_copy_pages, GFP_KERNEL);
+ if (!h_buf)
+ pr_err("Allocate hash buffer fail!");
+ }
#endif

error = memory_bm_create(&copy_bm, GFP_ATOMIC, PG_ANY);
@@ -2414,7 +2427,7 @@ int snapshot_write_next(struct snapshot_handle *handle)
if (IS_ERR(handle->buffer))
return PTR_ERR(handle->buffer);
#ifdef CONFIG_SNAPSHOT_VERIFICATION
- if (h_buf)
+ if (!capable(CAP_COMPROMISE_KERNEL) && h_buf)
*h_buf = handle->buffer;
#endif
}
@@ -2428,7 +2441,7 @@ int snapshot_write_next(struct snapshot_handle *handle)
if (handle->buffer != buffer)
handle->sync_read = 0;
#ifdef CONFIG_SNAPSHOT_VERIFICATION
- if (h_buf)
+ if (!capable(CAP_COMPROMISE_KERNEL) && h_buf)
*(h_buf + (handle->cur - nr_meta_pages - 1)) = handle->buffer;
/* Keep the buffer of sign key in snapshot */
if (pfn == skey_data_buf_pfn)
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index b5f8ce1..40225d7 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -1005,7 +1005,7 @@ static int load_image(struct swap_map_handle *handle,
if (!snapshot_image_loaded(snapshot))
ret = -ENODATA;
#ifdef CONFIG_SNAPSHOT_VERIFICATION
- else {
+ else if (!capable(CAP_COMPROMISE_KERNEL)) {
ret = snapshot_image_verify();
if (ret)
pr_info("PM: snapshot signature check FAIL: %d\n", ret);
@@ -1370,7 +1370,7 @@ out_finish:
}
}
#ifdef CONFIG_SNAPSHOT_VERIFICATION
- if (!ret) {
+ if (!ret && !capable(CAP_COMPROMISE_KERNEL)) {
ret = snapshot_image_verify();
if (ret)
pr_info("PM: snapshot signature check FAIL: %d\n", ret);
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 27b21ee..690f148 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -48,6 +48,14 @@ static int snapshot_open(struct inode *inode, struct file *filp)
struct snapshot_data *data;
int error;

+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
+#else
+ if (!capable(CAP_COMPROMISE_KERNEL)) {
+#endif
+ return -EPERM;
+ }
+
lock_system_sleep();

if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
@@ -255,6 +263,8 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
break;
}
#ifdef CONFIG_SNAPSHOT_VERIFICATION
+ if (capable(CAP_COMPROMISE_KERNEL))
+ goto skip_verify;
if (!snapshot_image_verify()) {
pr_info("PM: snapshot signature check SUCCESS!\n");
snapshot_fill_s4_skey();
@@ -263,6 +273,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
error = -EPERM;
break;
}
+skip_verify:
#endif
error = hibernation_restore(data->platform_support);
break;
--
1.6.4.2


2013-08-25 16:42:19

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> In current solution, the snapshot signature check used the RSA key-pair
> that are generated by bootloader(e.g. shim) and pass the key-pair to
> kernel through EFI variables. I choice to binding the snapshot
> signature check mechanism with UEFI secure boot for provide stronger
> protection of hibernate. Current behavior is following:
>
> + UEFI Secure Boot ON, Kernel found key-pair from shim:
> Will do the S4 signature check.
>
> + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> Will lock down S4 function.
>
> + UEFI Secure Boot OFF
> Will NOT do the S4 signature check.
> Ignore any keys from bootloader.
>
> v2:
> Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> is available for hibernate.
>
> Reviewed-by: Jiri Kosina <[email protected]>
> Signed-off-by: Lee, Chun-Yi <[email protected]>
> ---
> kernel/power/hibernate.c | 36 +++++++++++++++++-
> kernel/power/main.c | 11 +++++-
> kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> kernel/power/swap.c | 4 +-
> kernel/power/user.c | 11 +++++
> 5 files changed, 112 insertions(+), 45 deletions(-)
>
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index c545b15..0f19f3d 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -29,6 +29,7 @@
> #include <linux/ctype.h>
> #include <linux/genhd.h>
> #include <linux/key.h>
> +#include <linux/efi.h>
>
> #include "power.h"
>
> @@ -632,7 +633,14 @@ static void power_down(void)
> int hibernate(void)
> {
> int error;
> - int skey_error;
> +
> +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> +#else
> + if (!capable(CAP_COMPROMISE_KERNEL)) {
> +#endif
> + return -EPERM;
> + }
>
> lock_system_sleep();
> /* The snapshot device should not be opened while we're running */
> @@ -799,6 +807,15 @@ static int software_resume(void)
> if (error)
> goto Unlock;
>
> +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> +#else
> + if (!capable(CAP_COMPROMISE_KERNEL)) {
> +#endif
> + mutex_unlock(&pm_mutex);
> + return -EPERM;
> + }
> +
> /* The snapshot device should not be opened while we're running */
> if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> error = -EBUSY;
> @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> int i;
> char *start = buf;
>
> +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> +#else
> + if (efi_enabled(EFI_SECURE_BOOT)) {
> +#endif
> + buf += sprintf(buf, "[%s]\n", "disabled");
> + return buf-start;
> + }
> +
> for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> if (!hibernation_modes[i])
> continue;
> @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> char *p;
> int mode = HIBERNATION_INVALID;
>
> +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> +#else
> + if (!capable(CAP_COMPROMISE_KERNEL)) {
> +#endif
> + return -EPERM;
> + }
> +
> p = memchr(buf, '\n', n);
> len = p ? p - buf : n;
>

You clearly need some helper function.
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2013-08-27 10:14:37

by joeyli

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

於 日,2013-08-25 於 18:42 +0200,Pavel Machek 提到:
> On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> > In current solution, the snapshot signature check used the RSA key-pair
> > that are generated by bootloader(e.g. shim) and pass the key-pair to
> > kernel through EFI variables. I choice to binding the snapshot
> > signature check mechanism with UEFI secure boot for provide stronger
> > protection of hibernate. Current behavior is following:
> >
> > + UEFI Secure Boot ON, Kernel found key-pair from shim:
> > Will do the S4 signature check.
> >
> > + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> > Will lock down S4 function.
> >
> > + UEFI Secure Boot OFF
> > Will NOT do the S4 signature check.
> > Ignore any keys from bootloader.
> >
> > v2:
> > Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> > is available for hibernate.
> >
> > Reviewed-by: Jiri Kosina <[email protected]>
> > Signed-off-by: Lee, Chun-Yi <[email protected]>
> > ---
> > kernel/power/hibernate.c | 36 +++++++++++++++++-
> > kernel/power/main.c | 11 +++++-
> > kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> > kernel/power/swap.c | 4 +-
> > kernel/power/user.c | 11 +++++
> > 5 files changed, 112 insertions(+), 45 deletions(-)
> >
> > diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> > index c545b15..0f19f3d 100644
> > --- a/kernel/power/hibernate.c
> > +++ b/kernel/power/hibernate.c
> > @@ -29,6 +29,7 @@
> > #include <linux/ctype.h>
> > #include <linux/genhd.h>
> > #include <linux/key.h>
> > +#include <linux/efi.h>
> >
> > #include "power.h"
> >
> > @@ -632,7 +633,14 @@ static void power_down(void)
> > int hibernate(void)
> > {
> > int error;
> > - int skey_error;
> > +
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> >
> > lock_system_sleep();
> > /* The snapshot device should not be opened while we're running */
> > @@ -799,6 +807,15 @@ static int software_resume(void)
> > if (error)
> > goto Unlock;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + mutex_unlock(&pm_mutex);
> > + return -EPERM;
> > + }
> > +
> > /* The snapshot device should not be opened while we're running */
> > if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> > error = -EBUSY;
> > @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> > int i;
> > char *start = buf;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> > +#else
> > + if (efi_enabled(EFI_SECURE_BOOT)) {
> > +#endif
> > + buf += sprintf(buf, "[%s]\n", "disabled");
> > + return buf-start;
> > + }
> > +
> > for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> > if (!hibernation_modes[i])
> > continue;
> > @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> > char *p;
> > int mode = HIBERNATION_INVALID;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> > +
> > p = memchr(buf, '\n', n);
> > len = p ? p - buf : n;
> >
>
> You clearly need some helper function.
> Pavel
>

I will use a help function to replace those ifdef block.

Thanks for your suggestion!
Joey Lee


2013-08-27 10:14:37

by joeyli

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

於 日,2013-08-25 於 18:42 +0200,Pavel Machek 提到:
> On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> > In current solution, the snapshot signature check used the RSA key-pair
> > that are generated by bootloader(e.g. shim) and pass the key-pair to
> > kernel through EFI variables. I choice to binding the snapshot
> > signature check mechanism with UEFI secure boot for provide stronger
> > protection of hibernate. Current behavior is following:
> >
> > + UEFI Secure Boot ON, Kernel found key-pair from shim:
> > Will do the S4 signature check.
> >
> > + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> > Will lock down S4 function.
> >
> > + UEFI Secure Boot OFF
> > Will NOT do the S4 signature check.
> > Ignore any keys from bootloader.
> >
> > v2:
> > Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> > is available for hibernate.
> >
> > Reviewed-by: Jiri Kosina <[email protected]>
> > Signed-off-by: Lee, Chun-Yi <jlee-IBi9RG/[email protected]>
> > ---
> > kernel/power/hibernate.c | 36 +++++++++++++++++-
> > kernel/power/main.c | 11 +++++-
> > kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> > kernel/power/swap.c | 4 +-
> > kernel/power/user.c | 11 +++++
> > 5 files changed, 112 insertions(+), 45 deletions(-)
> >
> > diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> > index c545b15..0f19f3d 100644
> > --- a/kernel/power/hibernate.c
> > +++ b/kernel/power/hibernate.c
> > @@ -29,6 +29,7 @@
> > #include <linux/ctype.h>
> > #include <linux/genhd.h>
> > #include <linux/key.h>
> > +#include <linux/efi.h>
> >
> > #include "power.h"
> >
> > @@ -632,7 +633,14 @@ static void power_down(void)
> > int hibernate(void)
> > {
> > int error;
> > - int skey_error;
> > +
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> >
> > lock_system_sleep();
> > /* The snapshot device should not be opened while we're running */
> > @@ -799,6 +807,15 @@ static int software_resume(void)
> > if (error)
> > goto Unlock;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + mutex_unlock(&pm_mutex);
> > + return -EPERM;
> > + }
> > +
> > /* The snapshot device should not be opened while we're running */
> > if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> > error = -EBUSY;
> > @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> > int i;
> > char *start = buf;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> > +#else
> > + if (efi_enabled(EFI_SECURE_BOOT)) {
> > +#endif
> > + buf += sprintf(buf, "[%s]\n", "disabled");
> > + return buf-start;
> > + }
> > +
> > for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> > if (!hibernation_modes[i])
> > continue;
> > @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> > char *p;
> > int mode = HIBERNATION_INVALID;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> > +
> > p = memchr(buf, '\n', n);
> > len = p ? p - buf : n;
> >
>
> You clearly need some helper function.
> Pavel
>

I will use a help function to replace those ifdef block.

Thanks for your suggestion!
Joey Lee

2013-08-27 10:14:37

by joeyli

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

於 日,2013-08-25 於 18:42 +0200,Pavel Machek 提到:
> On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> > In current solution, the snapshot signature check used the RSA key-pair
> > that are generated by bootloader(e.g. shim) and pass the key-pair to
> > kernel through EFI variables. I choice to binding the snapshot
> > signature check mechanism with UEFI secure boot for provide stronger
> > protection of hibernate. Current behavior is following:
> >
> > + UEFI Secure Boot ON, Kernel found key-pair from shim:
> > Will do the S4 signature check.
> >
> > + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> > Will lock down S4 function.
> >
> > + UEFI Secure Boot OFF
> > Will NOT do the S4 signature check.
> > Ignore any keys from bootloader.
> >
> > v2:
> > Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> > is available for hibernate.
> >
> > Reviewed-by: Jiri Kosina <[email protected]>
> > Signed-off-by: Lee, Chun-Yi <[email protected]>
> > ---
> > kernel/power/hibernate.c | 36 +++++++++++++++++-
> > kernel/power/main.c | 11 +++++-
> > kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> > kernel/power/swap.c | 4 +-
> > kernel/power/user.c | 11 +++++
> > 5 files changed, 112 insertions(+), 45 deletions(-)
> >
> > diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> > index c545b15..0f19f3d 100644
> > --- a/kernel/power/hibernate.c
> > +++ b/kernel/power/hibernate.c
> > @@ -29,6 +29,7 @@
> > #include <linux/ctype.h>
> > #include <linux/genhd.h>
> > #include <linux/key.h>
> > +#include <linux/efi.h>
> >
> > #include "power.h"
> >
> > @@ -632,7 +633,14 @@ static void power_down(void)
> > int hibernate(void)
> > {
> > int error;
> > - int skey_error;
> > +
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> >
> > lock_system_sleep();
> > /* The snapshot device should not be opened while we're running */
> > @@ -799,6 +807,15 @@ static int software_resume(void)
> > if (error)
> > goto Unlock;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + mutex_unlock(&pm_mutex);
> > + return -EPERM;
> > + }
> > +
> > /* The snapshot device should not be opened while we're running */
> > if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> > error = -EBUSY;
> > @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> > int i;
> > char *start = buf;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> > +#else
> > + if (efi_enabled(EFI_SECURE_BOOT)) {
> > +#endif
> > + buf += sprintf(buf, "[%s]\n", "disabled");
> > + return buf-start;
> > + }
> > +
> > for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> > if (!hibernation_modes[i])
> > continue;
> > @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> > char *p;
> > int mode = HIBERNATION_INVALID;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> > +
> > p = memchr(buf, '\n', n);
> > len = p ? p - buf : n;
> >
>
> You clearly need some helper function.
> Pavel
>

I will use a help function to replace those ifdef block.

Thanks for your suggestion!
Joey Lee

2013-08-27 10:14:37

by joeyli

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

於 日,2013-08-25 於 18:42 +0200,Pavel Machek 提到:
> On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> > In current solution, the snapshot signature check used the RSA key-pair
> > that are generated by bootloader(e.g. shim) and pass the key-pair to
> > kernel through EFI variables. I choice to binding the snapshot
> > signature check mechanism with UEFI secure boot for provide stronger
> > protection of hibernate. Current behavior is following:
> >
> > + UEFI Secure Boot ON, Kernel found key-pair from shim:
> > Will do the S4 signature check.
> >
> > + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> > Will lock down S4 function.
> >
> > + UEFI Secure Boot OFF
> > Will NOT do the S4 signature check.
> > Ignore any keys from bootloader.
> >
> > v2:
> > Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> > is available for hibernate.
> >
> > Reviewed-by: Jiri Kosina <[email protected]>
> > Signed-off-by: Lee, Chun-Yi <[email protected]>
> > ---
> > kernel/power/hibernate.c | 36 +++++++++++++++++-
> > kernel/power/main.c | 11 +++++-
> > kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> > kernel/power/swap.c | 4 +-
> > kernel/power/user.c | 11 +++++
> > 5 files changed, 112 insertions(+), 45 deletions(-)
> >
> > diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> > index c545b15..0f19f3d 100644
> > --- a/kernel/power/hibernate.c
> > +++ b/kernel/power/hibernate.c
> > @@ -29,6 +29,7 @@
> > #include <linux/ctype.h>
> > #include <linux/genhd.h>
> > #include <linux/key.h>
> > +#include <linux/efi.h>
> >
> > #include "power.h"
> >
> > @@ -632,7 +633,14 @@ static void power_down(void)
> > int hibernate(void)
> > {
> > int error;
> > - int skey_error;
> > +
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> >
> > lock_system_sleep();
> > /* The snapshot device should not be opened while we're running */
> > @@ -799,6 +807,15 @@ static int software_resume(void)
> > if (error)
> > goto Unlock;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + mutex_unlock(&pm_mutex);
> > + return -EPERM;
> > + }
> > +
> > /* The snapshot device should not be opened while we're running */
> > if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> > error = -EBUSY;
> > @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> > int i;
> > char *start = buf;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> > +#else
> > + if (efi_enabled(EFI_SECURE_BOOT)) {
> > +#endif
> > + buf += sprintf(buf, "[%s]\n", "disabled");
> > + return buf-start;
> > + }
> > +
> > for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> > if (!hibernation_modes[i])
> > continue;
> > @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> > char *p;
> > int mode = HIBERNATION_INVALID;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> > +
> > p = memchr(buf, '\n', n);
> > len = p ? p - buf : n;
> >
>
> You clearly need some helper function.
> Pavel
>

I will use a help function to replace those ifdef block.

Thanks for your suggestion!
Joey Lee

2013-08-27 10:16:05

by joeyli

[permalink] [raw]
Subject: Re: [PATCH 15/18] Hibernate: adapt to UEFI secure boot with signature check

於 日,2013-08-25 於 18:42 +0200,Pavel Machek 提到:
> On Thu 2013-08-22 19:01:54, Lee, Chun-Yi wrote:
> > In current solution, the snapshot signature check used the RSA key-pair
> > that are generated by bootloader(e.g. shim) and pass the key-pair to
> > kernel through EFI variables. I choice to binding the snapshot
> > signature check mechanism with UEFI secure boot for provide stronger
> > protection of hibernate. Current behavior is following:
> >
> > + UEFI Secure Boot ON, Kernel found key-pair from shim:
> > Will do the S4 signature check.
> >
> > + UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
> > Will lock down S4 function.
> >
> > + UEFI Secure Boot OFF
> > Will NOT do the S4 signature check.
> > Ignore any keys from bootloader.
> >
> > v2:
> > Replace sign_key_data_loaded() by skey_data_available() to check sign key data
> > is available for hibernate.
> >
> > Reviewed-by: Jiri Kosina <[email protected]>
> > Signed-off-by: Lee, Chun-Yi <[email protected]>
> > ---
> > kernel/power/hibernate.c | 36 +++++++++++++++++-
> > kernel/power/main.c | 11 +++++-
> > kernel/power/snapshot.c | 95 ++++++++++++++++++++++++++--------------------
> > kernel/power/swap.c | 4 +-
> > kernel/power/user.c | 11 +++++
> > 5 files changed, 112 insertions(+), 45 deletions(-)
> >
> > diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> > index c545b15..0f19f3d 100644
> > --- a/kernel/power/hibernate.c
> > +++ b/kernel/power/hibernate.c
> > @@ -29,6 +29,7 @@
> > #include <linux/ctype.h>
> > #include <linux/genhd.h>
> > #include <linux/key.h>
> > +#include <linux/efi.h>
> >
> > #include "power.h"
> >
> > @@ -632,7 +633,14 @@ static void power_down(void)
> > int hibernate(void)
> > {
> > int error;
> > - int skey_error;
> > +
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> >
> > lock_system_sleep();
> > /* The snapshot device should not be opened while we're running */
> > @@ -799,6 +807,15 @@ static int software_resume(void)
> > if (error)
> > goto Unlock;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !wkey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + mutex_unlock(&pm_mutex);
> > + return -EPERM;
> > + }
> > +
> > /* The snapshot device should not be opened while we're running */
> > if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
> > error = -EBUSY;
> > @@ -892,6 +909,15 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
> > int i;
> > char *start = buf;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (efi_enabled(EFI_SECURE_BOOT) && !skey_data_available()) {
> > +#else
> > + if (efi_enabled(EFI_SECURE_BOOT)) {
> > +#endif
> > + buf += sprintf(buf, "[%s]\n", "disabled");
> > + return buf-start;
> > + }
> > +
> > for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
> > if (!hibernation_modes[i])
> > continue;
> > @@ -926,6 +952,14 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
> > char *p;
> > int mode = HIBERNATION_INVALID;
> >
> > +#ifdef CONFIG_SNAPSHOT_VERIFICATION
> > + if (!capable(CAP_COMPROMISE_KERNEL) && !skey_data_available()) {
> > +#else
> > + if (!capable(CAP_COMPROMISE_KERNEL)) {
> > +#endif
> > + return -EPERM;
> > + }
> > +
> > p = memchr(buf, '\n', n);
> > len = p ? p - buf : n;
> >
>
> You clearly need some helper function.
> Pavel
>

I will use a help function to replace those ifdef block.

Thanks for your suggestion!
Joey Lee