2022-04-14 19:21:56

by Jacky Li

[permalink] [raw]
Subject: [PATCH v2] crypto: ccp - Fix the INIT_EX data file open failure

There are 2 common cases when INIT_EX data file might not be
opened successfully and fail the sev initialization:

1. In user namespaces, normal user tasks (e.g. VMM) can change their
current->fs->root to point to arbitrary directories. While
init_ex_path is provided as a module param related to root file
system. Solution: use the root directory of init_task to avoid
accessing the wrong file.

2. Normal user tasks (e.g. VMM) don't have the privilege to access
the INIT_EX data file. Solution: open the file as root and
restore permissions immediately.

Fixes: 3d725965f836 ("crypto: ccp - Add SEV_INIT_EX support")
Signed-off-by: Jacky Li <[email protected]>
Reviewed-by: Peter Gonda <[email protected]>
---
Changelog since v1:
- Added Fixes tag and Reviewed-By tag.

drivers/crypto/ccp/sev-dev.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 6ab93dfd478a..3aefb177715e 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -23,6 +23,7 @@
#include <linux/gfp.h>
#include <linux/cpufeature.h>
#include <linux/fs.h>
+#include <linux/fs_struct.h>

#include <asm/smp.h>

@@ -170,6 +171,31 @@ static void *sev_fw_alloc(unsigned long len)
return page_address(page);
}

+static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
+{
+ struct file *fp;
+ struct path root;
+ struct cred *cred;
+ const struct cred *old_cred;
+
+ task_lock(&init_task);
+ get_fs_root(init_task.fs, &root);
+ task_unlock(&init_task);
+
+ cred = prepare_creds();
+ if (!cred)
+ return ERR_PTR(-ENOMEM);
+ cred->fsuid = GLOBAL_ROOT_UID;
+ old_cred = override_creds(cred);
+
+ fp = file_open_root(&root, filename, flags, mode);
+ path_put(&root);
+
+ revert_creds(old_cred);
+
+ return fp;
+}
+
static int sev_read_init_ex_file(void)
{
struct sev_device *sev = psp_master->sev_data;
@@ -181,7 +207,7 @@ static int sev_read_init_ex_file(void)
if (!sev_init_ex_buffer)
return -EOPNOTSUPP;

- fp = filp_open(init_ex_path, O_RDONLY, 0);
+ fp = open_file_as_root(init_ex_path, O_RDONLY, 0);
if (IS_ERR(fp)) {
int ret = PTR_ERR(fp);

@@ -217,7 +243,7 @@ static void sev_write_init_ex_file(void)
if (!sev_init_ex_buffer)
return;

- fp = filp_open(init_ex_path, O_CREAT | O_WRONLY, 0600);
+ fp = open_file_as_root(init_ex_path, O_CREAT | O_WRONLY, 0600);
if (IS_ERR(fp)) {
dev_err(sev->dev,
"SEV: could not open file for write, error %ld\n",
--
2.36.0.rc0.470.gd361397f0d-goog


2022-04-15 20:04:05

by Tom Lendacky

[permalink] [raw]
Subject: Re: [PATCH v2] crypto: ccp - Fix the INIT_EX data file open failure

On 4/14/22 11:23, Jacky Li wrote:
> There are 2 common cases when INIT_EX data file might not be
> opened successfully and fail the sev initialization:
>
> 1. In user namespaces, normal user tasks (e.g. VMM) can change their
> current->fs->root to point to arbitrary directories. While
> init_ex_path is provided as a module param related to root file
> system. Solution: use the root directory of init_task to avoid
> accessing the wrong file.
>
> 2. Normal user tasks (e.g. VMM) don't have the privilege to access
> the INIT_EX data file. Solution: open the file as root and
> restore permissions immediately.
>
> Fixes: 3d725965f836 ("crypto: ccp - Add SEV_INIT_EX support")
> Signed-off-by: Jacky Li <[email protected]>
> Reviewed-by: Peter Gonda <[email protected]>

Looks good, just a quick question. Should there be any type of access
checks before switching credentials? Should we check access to /dev/sev or
such? Or is the capability to load the module enough?

Thanks,
Tom

> ---
> Changelog since v1:
> - Added Fixes tag and Reviewed-By tag.
>
> drivers/crypto/ccp/sev-dev.c | 30 ++++++++++++++++++++++++++++--
> 1 file changed, 28 insertions(+), 2 deletions(-)
>

2022-04-21 15:32:13

by Tom Lendacky

[permalink] [raw]
Subject: Re: [PATCH v2] crypto: ccp - Fix the INIT_EX data file open failure

On 4/14/22 11:23, Jacky Li wrote:
> There are 2 common cases when INIT_EX data file might not be
> opened successfully and fail the sev initialization:
>
> 1. In user namespaces, normal user tasks (e.g. VMM) can change their
> current->fs->root to point to arbitrary directories. While
> init_ex_path is provided as a module param related to root file
> system. Solution: use the root directory of init_task to avoid
> accessing the wrong file.
>
> 2. Normal user tasks (e.g. VMM) don't have the privilege to access
> the INIT_EX data file. Solution: open the file as root and
> restore permissions immediately.
>
> Fixes: 3d725965f836 ("crypto: ccp - Add SEV_INIT_EX support")
> Signed-off-by: Jacky Li <[email protected]>
> Reviewed-by: Peter Gonda <[email protected]>

Acked-by: Tom Lendacky <[email protected]>

> ---
> Changelog since v1:
> - Added Fixes tag and Reviewed-By tag.
>
> drivers/crypto/ccp/sev-dev.c | 30 ++++++++++++++++++++++++++++--
> 1 file changed, 28 insertions(+), 2 deletions(-)
>