git: ce1895b7248d - stable/12 - CTL: Validate IOCTL parameters.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 14 Sep 2022 17:28:45 UTC
The branch stable/12 has been updated by mav:
URL: https://cgit.FreeBSD.org/src/commit/?id=ce1895b7248d5601b34d0d6492539a7081a8d451
commit ce1895b7248d5601b34d0d6492539a7081a8d451
Author: Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2022-09-07 01:58:27 +0000
Commit: Alexander Motin <mav@FreeBSD.org>
CommitDate: 2022-09-14 17:28:18 +0000
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
(cherry picked from commit 0586be48a97c5af50ba4f578d33211f81cc57016)
---
sys/cam/ctl/ctl.c | 14 ++++++++++++++
sys/cam/ctl/ctl_ioctl.h | 1 +
2 files changed, 15 insertions(+)
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index e909ccf70406..e0f30ebe1250 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -2904,6 +2904,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
}
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);
if (copyin(lun_req->args, packed, lun_req->args_len) != 0) {
free(packed, M_CTL);
@@ -2925,6 +2931,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
} else
lun_req->args_nvl = nvlist_create(0);
+ lun_req->result_nvl = NULL;
retval = backend->ioctl(dev, cmd, addr, flag, td);
nvlist_destroy(lun_req->args_nvl);
lun_req->args_nvl = tmp_args_nvl;
@@ -3181,6 +3188,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
}
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);
if (copyin(req->args, packed, req->args_len) != 0) {
free(packed, M_CTL);
@@ -3202,6 +3215,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
} else
req->args_nvl = nvlist_create(0);
+ req->result_nvl = NULL;
if (fe->ioctl)
retval = fe->ioctl(dev, cmd, addr, flag, td);
else
diff --git a/sys/cam/ctl/ctl_ioctl.h b/sys/cam/ctl/ctl_ioctl.h
index 49c48afbd766..e9caa3f0982b 100644
--- a/sys/cam/ctl/ctl_ioctl.h
+++ b/sys/cam/ctl/ctl_ioctl.h
@@ -460,6 +460,7 @@ struct ctl_lun_req {
union ctl_lunreq_data reqdata;
void * args;
nvlist_t * args_nvl;
+#define CTL_MAX_ARGS_LEN (1024 * 1024)
size_t args_len;
void * result;
nvlist_t * result_nvl;