Skip to content

Commit 44567ca

Browse files
steffen-eidenfrankjaa
authored andcommitted
s390/uvdevice: Add 'Add Secret' UVC
Userspace can call the Add Secret Ultravisor Call using IOCTLs on the uvdevice. The Add Secret UV call sends an encrypted and cryptographically verified request to the Ultravisor. The request inserts a protected guest's secret into the Ultravisor for later use. The uvdevice is merely transporting the request from userspace to the Ultravisor. It's neither checking nor manipulating the request data. Signed-off-by: Steffen Eiden <seiden@linux.ibm.com> Reviewed-by: Janosch Frank <frankja@linux.ibm.com> Link: https://lore.kernel.org/r/20230615100533.3996107-4-seiden@linux.ibm.com Signed-off-by: Janosch Frank <frankja@linux.ibm.com> Message-Id: <20230615100533.3996107-4-seiden@linux.ibm.com>
1 parent ea9d971 commit 44567ca

3 files changed

Lines changed: 81 additions & 0 deletions

File tree

arch/s390/include/asm/uv.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#define UVC_CMD_SET_SHARED_ACCESS 0x1000
5959
#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001
6060
#define UVC_CMD_RETR_ATTEST 0x1020
61+
#define UVC_CMD_ADD_SECRET 0x1031
6162

6263
/* Bits in installed uv calls */
6364
enum uv_cmds_inst {
@@ -88,6 +89,7 @@ enum uv_cmds_inst {
8889
BIT_UVC_CMD_DUMP_CPU = 26,
8990
BIT_UVC_CMD_DUMP_COMPLETE = 27,
9091
BIT_UVC_CMD_RETR_ATTEST = 28,
92+
BIT_UVC_CMD_ADD_SECRET = 29,
9193
};
9294

9395
enum uv_feat_ind {
@@ -292,6 +294,18 @@ struct uv_cb_dump_complete {
292294
u64 reserved30[5];
293295
} __packed __aligned(8);
294296

297+
/*
298+
* A common UV call struct for pv guests that contains a single address
299+
* Examples:
300+
* Add Secret
301+
*/
302+
struct uv_cb_guest_addr {
303+
struct uv_cb_header header;
304+
u64 reserved08[3];
305+
u64 addr;
306+
u64 reserved28[4];
307+
} __packed __aligned(8);
308+
295309
static inline int __uv_call(unsigned long r1, unsigned long r2)
296310
{
297311
int cc;

arch/s390/include/uapi/asm/uvdevice.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,27 @@ struct uvio_uvdev_info {
6969
#define UVIO_ATT_ARCB_MAX_LEN 0x100000
7070
#define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000
7171
#define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000
72+
#define UVIO_ADD_SECRET_MAX_LEN 0x100000
7273

7374
#define UVIO_DEVICE_NAME "uv"
7475
#define UVIO_TYPE_UVC 'u'
7576

7677
enum UVIO_IOCTL_NR {
7778
UVIO_IOCTL_UVDEV_INFO_NR = 0x00,
7879
UVIO_IOCTL_ATT_NR,
80+
UVIO_IOCTL_ADD_SECRET_NR,
7981
/* must be the last entry */
8082
UVIO_IOCTL_NUM_IOCTLS
8183
};
8284

8385
#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb)
8486
#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR)
8587
#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR)
88+
#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR)
8689

8790
#define UVIO_SUPP_CALL(nr) (1ULL << (nr))
8891
#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR)
8992
#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR)
93+
#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR)
9094

9195
#endif /* __S390_ASM_UVDEVICE_H */

drivers/s390/char/uvdevice.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
static const u32 ioctl_nr_to_uvc_bit[] __initconst = {
3838
[UVIO_IOCTL_UVDEV_INFO_NR] = BIT_UVIO_INTERNAL,
3939
[UVIO_IOCTL_ATT_NR] = BIT_UVC_CMD_RETR_ATTEST,
40+
[UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET,
4041
};
4142

4243
static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS);
@@ -231,6 +232,65 @@ static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl)
231232
return ret;
232233
}
233234

235+
/** uvio_add_secret() - perform an Add Secret UVC
236+
*
237+
* @uv_ioctl: ioctl control block
238+
*
239+
* uvio_add_secret() performs the Add Secret Ultravisor Call.
240+
*
241+
* The given userspace argument address and size are verified to be
242+
* valid but every other check is made by the Ultravisor
243+
* (UV). Therefore UV errors won't result in a negative return
244+
* value. The request is then copied to kernelspace, the UV-call is
245+
* performed and the results are copied back to userspace.
246+
*
247+
* The argument has to point to an Add Secret Request Control Block
248+
* which is an encrypted and cryptographically verified request that
249+
* inserts a protected guest's secrets into the Ultravisor for later
250+
* use.
251+
*
252+
* If the Add Secret UV facility is not present, UV will return
253+
* invalid command rc. This won't be fenced in the driver and does not
254+
* result in a negative return value.
255+
*
256+
* Context: might sleep
257+
*
258+
* Return: 0 on success or a negative error code on error.
259+
*/
260+
static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl)
261+
{
262+
void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
263+
struct uv_cb_guest_addr uvcb = {
264+
.header.len = sizeof(uvcb),
265+
.header.cmd = UVC_CMD_ADD_SECRET,
266+
};
267+
void *asrcb = NULL;
268+
int ret;
269+
270+
if (uv_ioctl->argument_len > UVIO_ADD_SECRET_MAX_LEN)
271+
return -EINVAL;
272+
if (uv_ioctl->argument_len == 0)
273+
return -EINVAL;
274+
275+
asrcb = kvzalloc(uv_ioctl->argument_len, GFP_KERNEL);
276+
if (!asrcb)
277+
return -ENOMEM;
278+
279+
ret = -EFAULT;
280+
if (copy_from_user(asrcb, user_buf_arg, uv_ioctl->argument_len))
281+
goto out;
282+
283+
ret = 0;
284+
uvcb.addr = (u64)asrcb;
285+
uv_call_sched(0, (u64)&uvcb);
286+
uv_ioctl->uv_rc = uvcb.header.rc;
287+
uv_ioctl->uv_rrc = uvcb.header.rrc;
288+
289+
out:
290+
kvfree(asrcb);
291+
return ret;
292+
}
293+
234294
static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp,
235295
unsigned long cmd)
236296
{
@@ -275,6 +335,9 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
275335
case UVIO_IOCTL_ATT_NR:
276336
ret = uvio_attestation(&uv_ioctl);
277337
break;
338+
case UVIO_IOCTL_ADD_SECRET_NR:
339+
ret = uvio_add_secret(&uv_ioctl);
340+
break;
278341
default:
279342
ret = -ENOIOCTLCMD;
280343
break;

0 commit comments

Comments
 (0)