CTL: Validate IOCTL parameters.
It was possible to cause kernel panic by passing too large args_len or non-NULL result_nvl. Though since the /dev/cam/ctl device is accessible only by root and used only by limited number of tools it was not a big problem. PR: 266115 PR: 266136 Reported by: Robert Morris <rtm@lcs.mit.edu> MFC after: 1 week
This commit is contained in:
parent
0fddee6d1f
commit
0586be48a9
@ -2977,6 +2977,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lun_req->args != NULL) {
|
if (lun_req->args != NULL) {
|
||||||
|
if (lun_req->args_len > CTL_MAX_ARGS_LEN) {
|
||||||
|
lun_req->status = CTL_LUN_ERROR;
|
||||||
|
snprintf(lun_req->error_str, sizeof(lun_req->error_str),
|
||||||
|
"Too big args.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
packed = malloc(lun_req->args_len, M_CTL, M_WAITOK);
|
packed = malloc(lun_req->args_len, M_CTL, M_WAITOK);
|
||||||
if (copyin(lun_req->args, packed, lun_req->args_len) != 0) {
|
if (copyin(lun_req->args, packed, lun_req->args_len) != 0) {
|
||||||
free(packed, M_CTL);
|
free(packed, M_CTL);
|
||||||
@ -2998,6 +3004,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
|||||||
} else
|
} else
|
||||||
lun_req->args_nvl = nvlist_create(0);
|
lun_req->args_nvl = nvlist_create(0);
|
||||||
|
|
||||||
|
lun_req->result_nvl = NULL;
|
||||||
retval = backend->ioctl(dev, cmd, addr, flag, td);
|
retval = backend->ioctl(dev, cmd, addr, flag, td);
|
||||||
nvlist_destroy(lun_req->args_nvl);
|
nvlist_destroy(lun_req->args_nvl);
|
||||||
lun_req->args_nvl = tmp_args_nvl;
|
lun_req->args_nvl = tmp_args_nvl;
|
||||||
@ -3254,6 +3261,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req->args != NULL) {
|
if (req->args != NULL) {
|
||||||
|
if (req->args_len > CTL_MAX_ARGS_LEN) {
|
||||||
|
req->status = CTL_LUN_ERROR;
|
||||||
|
snprintf(req->error_str, sizeof(req->error_str),
|
||||||
|
"Too big args.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
packed = malloc(req->args_len, M_CTL, M_WAITOK);
|
packed = malloc(req->args_len, M_CTL, M_WAITOK);
|
||||||
if (copyin(req->args, packed, req->args_len) != 0) {
|
if (copyin(req->args, packed, req->args_len) != 0) {
|
||||||
free(packed, M_CTL);
|
free(packed, M_CTL);
|
||||||
@ -3275,6 +3288,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
|||||||
} else
|
} else
|
||||||
req->args_nvl = nvlist_create(0);
|
req->args_nvl = nvlist_create(0);
|
||||||
|
|
||||||
|
req->result_nvl = NULL;
|
||||||
if (fe->ioctl)
|
if (fe->ioctl)
|
||||||
retval = fe->ioctl(dev, cmd, addr, flag, td);
|
retval = fe->ioctl(dev, cmd, addr, flag, td);
|
||||||
else
|
else
|
||||||
|
@ -460,6 +460,7 @@ struct ctl_lun_req {
|
|||||||
union ctl_lunreq_data reqdata;
|
union ctl_lunreq_data reqdata;
|
||||||
void * args;
|
void * args;
|
||||||
nvlist_t * args_nvl;
|
nvlist_t * args_nvl;
|
||||||
|
#define CTL_MAX_ARGS_LEN (1024 * 1024)
|
||||||
size_t args_len;
|
size_t args_len;
|
||||||
void * result;
|
void * result;
|
||||||
nvlist_t * result_nvl;
|
nvlist_t * result_nvl;
|
||||||
|
Loading…
Reference in New Issue
Block a user