Skip to content

Commit b610281

Browse files
Connor Kuehlherbertx
authored andcommitted
crypto: ccp - use file mode for sev ioctl permissions
Instead of using CAP_SYS_ADMIN which is restricted to the root user, check the file mode for write permissions before executing commands that can affect the platform. This allows for more fine-grained access control to the SEV ioctl interface. This would allow a SEV-only user or group the ability to administer the platform without requiring them to be root or granting them overly powerful permissions. For example: chown root:root /dev/sev chmod 600 /dev/sev setfacl -m g:sev:r /dev/sev setfacl -m g:sev-admin:rw /dev/sev In this instance, members of the "sev-admin" group have the ability to perform all ioctl calls (including the ones that modify platform state). Members of the "sev" group only have access to the ioctls that do not modify the platform state. This also makes opening "/dev/sev" more consistent with how file descriptors are usually handled. By only checking for CAP_SYS_ADMIN, the file descriptor could be opened read-only but could still execute ioctls that modify the platform state. This patch enforces that the file descriptor is opened with write privileges if it is going to be used to modify the platform state. This flexibility is completely opt-in, and if it is not desirable by the administrator then they do not need to give anyone else access to /dev/sev. Signed-off-by: Connor Kuehl <[email protected]> Reviewed-by: Brijesh Singh <[email protected]> Reviewed-by: Bandan Das <[email protected]> Acked-by: David Rientjes <[email protected]> Acked-by: Tom Lendacky <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent f086fd1 commit b610281

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

drivers/crypto/ccp/sev-dev.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,11 @@ static int sev_get_platform_state(int *state, int *error)
283283
return rc;
284284
}
285285

286-
static int sev_ioctl_do_reset(struct sev_issue_cmd *argp)
286+
static int sev_ioctl_do_reset(struct sev_issue_cmd *argp, bool writable)
287287
{
288288
int state, rc;
289289

290-
if (!capable(CAP_SYS_ADMIN))
290+
if (!writable)
291291
return -EPERM;
292292

293293
/*
@@ -331,12 +331,12 @@ static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
331331
return ret;
332332
}
333333

334-
static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
334+
static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp, bool writable)
335335
{
336336
struct sev_device *sev = psp_master->sev_data;
337337
int rc;
338338

339-
if (!capable(CAP_SYS_ADMIN))
339+
if (!writable)
340340
return -EPERM;
341341

342342
if (sev->state == SEV_STATE_UNINIT) {
@@ -348,15 +348,15 @@ static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
348348
return __sev_do_cmd_locked(cmd, NULL, &argp->error);
349349
}
350350

351-
static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp)
351+
static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable)
352352
{
353353
struct sev_device *sev = psp_master->sev_data;
354354
struct sev_user_data_pek_csr input;
355355
struct sev_data_pek_csr *data;
356356
void *blob = NULL;
357357
int ret;
358358

359-
if (!capable(CAP_SYS_ADMIN))
359+
if (!writable)
360360
return -EPERM;
361361

362362
if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
@@ -539,15 +539,15 @@ static int sev_update_firmware(struct device *dev)
539539
return ret;
540540
}
541541

542-
static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
542+
static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp, bool writable)
543543
{
544544
struct sev_device *sev = psp_master->sev_data;
545545
struct sev_user_data_pek_cert_import input;
546546
struct sev_data_pek_cert_import *data;
547547
void *pek_blob, *oca_blob;
548548
int ret;
549549

550-
if (!capable(CAP_SYS_ADMIN))
550+
if (!writable)
551551
return -EPERM;
552552

553553
if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
@@ -698,7 +698,7 @@ static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)
698698
return ret;
699699
}
700700

701-
static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)
701+
static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
702702
{
703703
struct sev_device *sev = psp_master->sev_data;
704704
struct sev_user_data_pdh_cert_export input;
@@ -708,7 +708,7 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)
708708

709709
/* If platform is not in INIT state then transition it to INIT. */
710710
if (sev->state != SEV_STATE_INIT) {
711-
if (!capable(CAP_SYS_ADMIN))
711+
if (!writable)
712712
return -EPERM;
713713

714714
ret = __sev_platform_init_locked(&argp->error);
@@ -801,6 +801,7 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
801801
void __user *argp = (void __user *)arg;
802802
struct sev_issue_cmd input;
803803
int ret = -EFAULT;
804+
bool writable = file->f_mode & FMODE_WRITE;
804805

805806
if (!psp_master || !psp_master->sev_data)
806807
return -ENODEV;
@@ -819,25 +820,25 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
819820
switch (input.cmd) {
820821

821822
case SEV_FACTORY_RESET:
822-
ret = sev_ioctl_do_reset(&input);
823+
ret = sev_ioctl_do_reset(&input, writable);
823824
break;
824825
case SEV_PLATFORM_STATUS:
825826
ret = sev_ioctl_do_platform_status(&input);
826827
break;
827828
case SEV_PEK_GEN:
828-
ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PEK_GEN, &input);
829+
ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PEK_GEN, &input, writable);
829830
break;
830831
case SEV_PDH_GEN:
831-
ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PDH_GEN, &input);
832+
ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PDH_GEN, &input, writable);
832833
break;
833834
case SEV_PEK_CSR:
834-
ret = sev_ioctl_do_pek_csr(&input);
835+
ret = sev_ioctl_do_pek_csr(&input, writable);
835836
break;
836837
case SEV_PEK_CERT_IMPORT:
837-
ret = sev_ioctl_do_pek_import(&input);
838+
ret = sev_ioctl_do_pek_import(&input, writable);
838839
break;
839840
case SEV_PDH_CERT_EXPORT:
840-
ret = sev_ioctl_do_pdh_export(&input);
841+
ret = sev_ioctl_do_pdh_export(&input, writable);
841842
break;
842843
case SEV_GET_ID:
843844
pr_warn_once("SEV_GET_ID command is deprecated, use SEV_GET_ID2\n");

0 commit comments

Comments
 (0)