Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <jackyli@google.com>
Reviewed-by: Peter Gonda <pgonda@google.com>
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Jacky Li and committed by
Herbert Xu
05def5ca c6d3ffae

+28 -2
+28 -2
drivers/crypto/ccp/sev-dev.c
··· 23 23 #include <linux/gfp.h> 24 24 #include <linux/cpufeature.h> 25 25 #include <linux/fs.h> 26 + #include <linux/fs_struct.h> 26 27 27 28 #include <asm/smp.h> 28 29 ··· 171 170 return page_address(page); 172 171 } 173 172 173 + static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) 174 + { 175 + struct file *fp; 176 + struct path root; 177 + struct cred *cred; 178 + const struct cred *old_cred; 179 + 180 + task_lock(&init_task); 181 + get_fs_root(init_task.fs, &root); 182 + task_unlock(&init_task); 183 + 184 + cred = prepare_creds(); 185 + if (!cred) 186 + return ERR_PTR(-ENOMEM); 187 + cred->fsuid = GLOBAL_ROOT_UID; 188 + old_cred = override_creds(cred); 189 + 190 + fp = file_open_root(&root, filename, flags, mode); 191 + path_put(&root); 192 + 193 + revert_creds(old_cred); 194 + 195 + return fp; 196 + } 197 + 174 198 static int sev_read_init_ex_file(void) 175 199 { 176 200 struct sev_device *sev = psp_master->sev_data; ··· 207 181 if (!sev_init_ex_buffer) 208 182 return -EOPNOTSUPP; 209 183 210 - fp = filp_open(init_ex_path, O_RDONLY, 0); 184 + fp = open_file_as_root(init_ex_path, O_RDONLY, 0); 211 185 if (IS_ERR(fp)) { 212 186 int ret = PTR_ERR(fp); 213 187 ··· 243 217 if (!sev_init_ex_buffer) 244 218 return; 245 219 246 - fp = filp_open(init_ex_path, O_CREAT | O_WRONLY, 0600); 220 + fp = open_file_as_root(init_ex_path, O_CREAT | O_WRONLY, 0600); 247 221 if (IS_ERR(fp)) { 248 222 dev_err(sev->dev, 249 223 "SEV: could not open file for write, error %ld\n",