Skip to content

Commit 2d786e6

Browse files
Ming Leiaxboe
authored andcommitted
block: ublk: switch to ioctl command encoding
All ublk commands(control, IO) should have taken ioctl command encoding from the beginning, because ioctl command encoding defines each code uniquely, so driver can figure out wrong command sent from userspace easily; 2) it might help security subsystem for audit uring cmd[1]. Unfortunately we didn't do that way, and it could be one lesson for ublk driver. So switch to ioctl command encoding now, we still support commands encoded in old way, but they become legacy definition. Any new command should take ioctl encoding. See ublksrv code for switching to ioctl command encoding in [2]. [1] https://lore.kernel.org/io-uring/CAHC9VhSVzujW9LOj5Km80AjU0EfAuukoLrxO6BEfnXeK_s6bAg@mail.gmail.com/ [2] https://github.com/ming1/ubdsrv/commits/ioctl_cmd_encoding Cc: Christoph Hellwig <[email protected]> Cc: Ken Kurematsu <[email protected]> Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 26a42b6 commit 2d786e6

File tree

3 files changed

+94
-13
lines changed

3 files changed

+94
-13
lines changed

drivers/block/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,23 @@ config BLK_DEV_UBLK
385385
can handle batch more effectively, but task_work_add() isn't exported
386386
for module, so ublk has to be built to kernel.
387387

388+
config BLKDEV_UBLK_LEGACY_OPCODES
389+
bool "Support legacy command opcode"
390+
depends on BLK_DEV_UBLK
391+
default y
392+
help
393+
ublk driver started to take plain command encoding, which turns out
394+
one bad way. The traditional ioctl command opcode encodes more
395+
info and basically defines each code uniquely, so opcode conflict
396+
is avoided, and driver can handle wrong command easily, meantime it
397+
may help security subsystem to audit io_uring command.
398+
399+
Say Y if your application still uses legacy command opcode.
400+
401+
Say N if you don't want to support legacy command opcode. It is
402+
suggested to enable N if your application(ublk server) switches to
403+
ioctl command encoding.
404+
388405
source "drivers/block/rnbd/Kconfig"
389406

390407
endif # BLK_DEV

drivers/block/ublk_drv.c

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
| UBLK_F_NEED_GET_DATA \
5454
| UBLK_F_USER_RECOVERY \
5555
| UBLK_F_USER_RECOVERY_REISSUE \
56-
| UBLK_F_UNPRIVILEGED_DEV)
56+
| UBLK_F_UNPRIVILEGED_DEV \
57+
| UBLK_F_CMD_IOCTL_ENCODE)
5758

5859
/* All UBLK_PARAM_TYPE_* should be included here */
5960
#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \
@@ -1253,6 +1254,19 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
12531254
ublk_queue_cmd(ubq, req);
12541255
}
12551256

1257+
static inline int ublk_check_cmd_op(u32 cmd_op)
1258+
{
1259+
u32 ioc_type = _IOC_TYPE(cmd_op);
1260+
1261+
if (IS_ENABLED(CONFIG_BLKDEV_UBLK_LEGACY_OPCODES) && ioc_type != 'u')
1262+
return -EOPNOTSUPP;
1263+
1264+
if (ioc_type != 'u' && ioc_type != 0)
1265+
return -EOPNOTSUPP;
1266+
1267+
return 0;
1268+
}
1269+
12561270
static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
12571271
{
12581272
struct ublksrv_io_cmd *ub_cmd = (struct ublksrv_io_cmd *)cmd->cmd;
@@ -1294,10 +1308,14 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
12941308
* iff the driver have set the UBLK_IO_FLAG_NEED_GET_DATA.
12951309
*/
12961310
if ((!!(io->flags & UBLK_IO_FLAG_NEED_GET_DATA))
1297-
^ (cmd_op == UBLK_IO_NEED_GET_DATA))
1311+
^ (_IOC_NR(cmd_op) == UBLK_IO_NEED_GET_DATA))
1312+
goto out;
1313+
1314+
ret = ublk_check_cmd_op(cmd_op);
1315+
if (ret)
12981316
goto out;
12991317

1300-
switch (cmd_op) {
1318+
switch (_IOC_NR(cmd_op)) {
13011319
case UBLK_IO_FETCH_REQ:
13021320
/* UBLK_IO_FETCH_REQ is only allowed before queue is setup */
13031321
if (ublk_queue_ready(ubq)) {
@@ -1743,6 +1761,8 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
17431761
if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK))
17441762
ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK;
17451763

1764+
ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE;
1765+
17461766
/* We are not ready to support zero copy */
17471767
ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;
17481768

@@ -2099,7 +2119,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
20992119
* know if the specified device is created as unprivileged
21002120
* mode.
21012121
*/
2102-
if (cmd->cmd_op != UBLK_CMD_GET_DEV_INFO2)
2122+
if (_IOC_NR(cmd->cmd_op) != UBLK_CMD_GET_DEV_INFO2)
21032123
return 0;
21042124
}
21052125

@@ -2125,7 +2145,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub,
21252145
dev_path[header->dev_path_len] = 0;
21262146

21272147
ret = -EINVAL;
2128-
switch (cmd->cmd_op) {
2148+
switch (_IOC_NR(cmd->cmd_op)) {
21292149
case UBLK_CMD_GET_DEV_INFO:
21302150
case UBLK_CMD_GET_DEV_INFO2:
21312151
case UBLK_CMD_GET_QUEUE_AFFINITY:
@@ -2164,6 +2184,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
21642184
{
21652185
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
21662186
struct ublk_device *ub = NULL;
2187+
u32 cmd_op = cmd->cmd_op;
21672188
int ret = -EINVAL;
21682189

21692190
if (issue_flags & IO_URING_F_NONBLOCK)
@@ -2174,22 +2195,22 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
21742195
if (!(issue_flags & IO_URING_F_SQE128))
21752196
goto out;
21762197

2177-
if (cmd->cmd_op != UBLK_CMD_ADD_DEV) {
2198+
ret = ublk_check_cmd_op(cmd_op);
2199+
if (ret)
2200+
goto out;
2201+
2202+
if (_IOC_NR(cmd_op) != UBLK_CMD_ADD_DEV) {
21782203
ret = -ENODEV;
21792204
ub = ublk_get_device_from_id(header->dev_id);
21802205
if (!ub)
21812206
goto out;
21822207

21832208
ret = ublk_ctrl_uring_cmd_permission(ub, cmd);
2184-
} else {
2185-
/* ADD_DEV permission check is done in command handler */
2186-
ret = 0;
2209+
if (ret)
2210+
goto put_dev;
21872211
}
21882212

2189-
if (ret)
2190-
goto put_dev;
2191-
2192-
switch (cmd->cmd_op) {
2213+
switch (_IOC_NR(cmd_op)) {
21932214
case UBLK_CMD_START_DEV:
21942215
ret = ublk_ctrl_start_dev(ub, cmd);
21952216
break;

include/uapi/linux/ublk_cmd.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
/*
1010
* Admin commands, issued by ublk server, and handled by ublk driver.
11+
*
12+
* Legacy command definition, don't use in new application, and don't
13+
* add new such definition any more
1114
*/
1215
#define UBLK_CMD_GET_QUEUE_AFFINITY 0x01
1316
#define UBLK_CMD_GET_DEV_INFO 0x02
@@ -21,6 +24,30 @@
2124
#define UBLK_CMD_END_USER_RECOVERY 0x11
2225
#define UBLK_CMD_GET_DEV_INFO2 0x12
2326

27+
/* Any new ctrl command should encode by __IO*() */
28+
#define UBLK_U_CMD_GET_QUEUE_AFFINITY \
29+
_IOR('u', UBLK_CMD_GET_QUEUE_AFFINITY, struct ublksrv_ctrl_cmd)
30+
#define UBLK_U_CMD_GET_DEV_INFO \
31+
_IOR('u', UBLK_CMD_GET_DEV_INFO, struct ublksrv_ctrl_cmd)
32+
#define UBLK_U_CMD_ADD_DEV \
33+
_IOWR('u', UBLK_CMD_ADD_DEV, struct ublksrv_ctrl_cmd)
34+
#define UBLK_U_CMD_DEL_DEV \
35+
_IOWR('u', UBLK_CMD_DEL_DEV, struct ublksrv_ctrl_cmd)
36+
#define UBLK_U_CMD_START_DEV \
37+
_IOWR('u', UBLK_CMD_START_DEV, struct ublksrv_ctrl_cmd)
38+
#define UBLK_U_CMD_STOP_DEV \
39+
_IOWR('u', UBLK_CMD_STOP_DEV, struct ublksrv_ctrl_cmd)
40+
#define UBLK_U_CMD_SET_PARAMS \
41+
_IOWR('u', UBLK_CMD_SET_PARAMS, struct ublksrv_ctrl_cmd)
42+
#define UBLK_U_CMD_GET_PARAMS \
43+
_IOR('u', UBLK_CMD_GET_PARAMS, struct ublksrv_ctrl_cmd)
44+
#define UBLK_U_CMD_START_USER_RECOVERY \
45+
_IOWR('u', UBLK_CMD_START_USER_RECOVERY, struct ublksrv_ctrl_cmd)
46+
#define UBLK_U_CMD_END_USER_RECOVERY \
47+
_IOWR('u', UBLK_CMD_END_USER_RECOVERY, struct ublksrv_ctrl_cmd)
48+
#define UBLK_U_CMD_GET_DEV_INFO2 \
49+
_IOR('u', UBLK_CMD_GET_DEV_INFO2, struct ublksrv_ctrl_cmd)
50+
2451
/*
2552
* IO commands, issued by ublk server, and handled by ublk driver.
2653
*
@@ -41,10 +68,23 @@
4168
* It is only used if ublksrv set UBLK_F_NEED_GET_DATA flag
4269
* while starting a ublk device.
4370
*/
71+
72+
/*
73+
* Legacy IO command definition, don't use in new application, and don't
74+
* add new such definition any more
75+
*/
4476
#define UBLK_IO_FETCH_REQ 0x20
4577
#define UBLK_IO_COMMIT_AND_FETCH_REQ 0x21
4678
#define UBLK_IO_NEED_GET_DATA 0x22
4779

80+
/* Any new IO command should encode by __IOWR() */
81+
#define UBLK_U_IO_FETCH_REQ \
82+
_IOWR('u', UBLK_IO_FETCH_REQ, struct ublksrv_io_cmd)
83+
#define UBLK_U_IO_COMMIT_AND_FETCH_REQ \
84+
_IOWR('u', UBLK_IO_COMMIT_AND_FETCH_REQ, struct ublksrv_io_cmd)
85+
#define UBLK_U_IO_NEED_GET_DATA \
86+
_IOWR('u', UBLK_IO_NEED_GET_DATA, struct ublksrv_io_cmd)
87+
4888
/* only ABORT means that no re-fetch */
4989
#define UBLK_IO_RES_OK 0
5090
#define UBLK_IO_RES_NEED_GET_DATA 1
@@ -102,6 +142,9 @@
102142
*/
103143
#define UBLK_F_UNPRIVILEGED_DEV (1UL << 5)
104144

145+
/* use ioctl encoding for uring command */
146+
#define UBLK_F_CMD_IOCTL_ENCODE (1UL << 6)
147+
105148
/* device state */
106149
#define UBLK_S_DEV_DEAD 0
107150
#define UBLK_S_DEV_LIVE 1

0 commit comments

Comments
 (0)