mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
ksmbd: prevent out-of-bounds reads in share config responses
Validate IPC share configuration payload sizes before consuming
variable-length fields. Bound veto list parsing and account for
the separator byte when deriving the path length.
Fixes: a677ebd8ca ("ksmbd: validate payload size in ipc response")
Reported-by: Kanishka De Silva <kpskanna1915@gmail.com>
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
feca5e70fc
commit
f25e93768f
|
|
@ -146,9 +146,9 @@ static struct ksmbd_share_config *__share_lookup(const char *name)
|
|||
|
||||
static int parse_veto_list(struct ksmbd_share_config *share,
|
||||
char *veto_list,
|
||||
int veto_list_sz)
|
||||
size_t veto_list_sz)
|
||||
{
|
||||
int sz = 0;
|
||||
size_t sz;
|
||||
|
||||
if (!veto_list_sz)
|
||||
return 0;
|
||||
|
|
@ -156,7 +156,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
|
|||
while (veto_list_sz > 0) {
|
||||
struct ksmbd_veto_pattern *p;
|
||||
|
||||
sz = strlen(veto_list);
|
||||
sz = strnlen(veto_list, veto_list_sz);
|
||||
if (!sz)
|
||||
break;
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
|
|||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
|
||||
p->pattern = kstrndup(veto_list, sz, KSMBD_DEFAULT_GFP);
|
||||
if (!p->pattern) {
|
||||
kfree(p);
|
||||
return -ENOMEM;
|
||||
|
|
@ -172,6 +172,9 @@ static int parse_veto_list(struct ksmbd_share_config *share,
|
|||
|
||||
list_add(&p->list, &share->veto_list);
|
||||
|
||||
if (sz == veto_list_sz)
|
||||
break;
|
||||
|
||||
veto_list += sz + 1;
|
||||
veto_list_sz -= (sz + 1);
|
||||
}
|
||||
|
|
@ -224,17 +227,28 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
|
|||
}
|
||||
|
||||
if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
|
||||
int path_len = PATH_MAX;
|
||||
size_t path_len;
|
||||
|
||||
if (resp->payload_sz)
|
||||
path_len = resp->payload_sz - resp->veto_list_sz;
|
||||
|
||||
share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
|
||||
KSMBD_DEFAULT_GFP);
|
||||
if (!share->path) {
|
||||
ret = -ENOMEM;
|
||||
if (resp->payload_sz <= resp->veto_list_sz) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
path_len = resp->payload_sz - resp->veto_list_sz;
|
||||
if (resp->veto_list_sz)
|
||||
path_len--;
|
||||
|
||||
if (!path_len) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
share->path = kstrndup(
|
||||
ksmbd_share_config_path(resp),
|
||||
path_len, KSMBD_DEFAULT_GFP);
|
||||
if (!share->path)
|
||||
ret = -ENOMEM;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (share->path) {
|
||||
share->path_sz = strlen(share->path);
|
||||
while (share->path_sz > 1 &&
|
||||
share->path[share->path_sz - 1] == '/')
|
||||
|
|
|
|||
|
|
@ -532,14 +532,21 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
|
|||
if (entry->msg_sz < sizeof(struct ksmbd_share_config_response))
|
||||
return -EINVAL;
|
||||
|
||||
if (resp->payload_sz) {
|
||||
if (resp->payload_sz < resp->veto_list_sz)
|
||||
return -EINVAL;
|
||||
if (strnlen(resp->share_name, sizeof(resp->share_name)) ==
|
||||
sizeof(resp->share_name))
|
||||
return -EINVAL;
|
||||
|
||||
if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
|
||||
resp->payload_sz, &msg_sz))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (resp->veto_list_sz > resp->payload_sz)
|
||||
return -EINVAL;
|
||||
|
||||
if (resp->flags != KSMBD_SHARE_FLAG_INVALID &&
|
||||
!(resp->flags & KSMBD_SHARE_FLAG_PIPE) &&
|
||||
resp->payload_sz <= resp->veto_list_sz)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
|
||||
resp->payload_sz, &msg_sz))
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
case KSMBD_EVENT_LOGIN_REQUEST_EXT:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user