mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
3 ksmbd fixes: including an important security fix for path processing, and a buffer overflow check, and a trivial fix for incorrect header inclusion
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmFHRVAACgkQiiy9cAdy T1F0zwv/RC2quL/y+DjNOKbTZwaExLSaZlsww23XghVXIlYMMy4pENpYsu+tjW+l aEEsIciGBBQ40/Q0Eu2ttk8vIUpaI2SxM+KlCufjX61Rlve42eWZBZ1KkrijKIq4 xvMBJLAg9Jhq1JLl58nyIHb4XV0N9sVELd3aNyEM+4b/2kEe59qW1FdFAXOS3GOc kkHEWIDnoYs/sCpKey2UuJmI9D2BbxZwhrW6r7mmyq7PQmbPuggSAnL8m5tIsv7Y GHqmhaaJovfbOJ5L+BUblRyqMgDoYaxiyk3ujHdJkWUkeSpCfQhelUyT30xGzhTV AQhVrAjB6ozcm/F0lLW9J8LUL0ESDQVUbEMEK1W2GyaR24oQ2sxj6VzILBMne+oh 7QyHbd7N302f+yTvYQbeX9TKd3slh+oOUVAANWDpPfiFhF09iKdjaY3iAUSsf339 nBO4/LlcpELb51UhHEsE1SfP2EbtJwvIMsFGnct6qyQoYM7giacP0AEs/RQhXMwW XMddUoON =vPyV -----END PGP SIGNATURE----- Merge tag '5.15-rc1-ksmbd' of git://git.samba.org/ksmbd Pull ksmbd server fixes from Steve French: "Three ksmbd fixes, including an important security fix for path processing, and a buffer overflow check, and a trivial fix for incorrect header inclusion" * tag '5.15-rc1-ksmbd' of git://git.samba.org/ksmbd: ksmbd: add validation for FILE_FULL_EA_INFORMATION of smb2_get_info ksmbd: prevent out of share access ksmbd: transport_rdma: Don't include rwlock.h directly
This commit is contained in:
commit
707a63e9a9
@ -191,19 +191,77 @@ int get_nlink(struct kstat *st)
|
||||
return nlink;
|
||||
}
|
||||
|
||||
void ksmbd_conv_path_to_unix(char *path)
|
||||
char *ksmbd_conv_path_to_unix(char *path)
|
||||
{
|
||||
size_t path_len, remain_path_len, out_path_len;
|
||||
char *out_path, *out_next;
|
||||
int i, pre_dotdot_cnt = 0, slash_cnt = 0;
|
||||
bool is_last;
|
||||
|
||||
strreplace(path, '\\', '/');
|
||||
}
|
||||
path_len = strlen(path);
|
||||
remain_path_len = path_len;
|
||||
if (path_len == 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
void ksmbd_strip_last_slash(char *path)
|
||||
{
|
||||
int len = strlen(path);
|
||||
out_path = kzalloc(path_len + 2, GFP_KERNEL);
|
||||
if (!out_path)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
out_path_len = 0;
|
||||
out_next = out_path;
|
||||
|
||||
while (len && path[len - 1] == '/') {
|
||||
path[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
do {
|
||||
char *name = path + path_len - remain_path_len;
|
||||
char *next = strchrnul(name, '/');
|
||||
size_t name_len = next - name;
|
||||
|
||||
is_last = !next[0];
|
||||
if (name_len == 2 && name[0] == '.' && name[1] == '.') {
|
||||
pre_dotdot_cnt++;
|
||||
/* handle the case that path ends with "/.." */
|
||||
if (is_last)
|
||||
goto follow_dotdot;
|
||||
} else {
|
||||
if (pre_dotdot_cnt) {
|
||||
follow_dotdot:
|
||||
slash_cnt = 0;
|
||||
for (i = out_path_len - 1; i >= 0; i--) {
|
||||
if (out_path[i] == '/' &&
|
||||
++slash_cnt == pre_dotdot_cnt + 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 &&
|
||||
slash_cnt != pre_dotdot_cnt) {
|
||||
kfree(out_path);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
out_next = &out_path[i+1];
|
||||
*out_next = '\0';
|
||||
out_path_len = i + 1;
|
||||
|
||||
}
|
||||
|
||||
if (name_len != 0 &&
|
||||
!(name_len == 1 && name[0] == '.') &&
|
||||
!(name_len == 2 && name[0] == '.' && name[1] == '.')) {
|
||||
next[0] = '\0';
|
||||
sprintf(out_next, "%s/", name);
|
||||
out_next += name_len + 1;
|
||||
out_path_len += name_len + 1;
|
||||
next[0] = '/';
|
||||
}
|
||||
pre_dotdot_cnt = 0;
|
||||
}
|
||||
|
||||
remain_path_len -= name_len + 1;
|
||||
} while (!is_last);
|
||||
|
||||
if (out_path_len > 0)
|
||||
out_path[out_path_len-1] = '\0';
|
||||
path[path_len] = '\0';
|
||||
return out_path;
|
||||
}
|
||||
|
||||
void ksmbd_conv_path_to_windows(char *path)
|
||||
|
@ -16,8 +16,7 @@ int ksmbd_validate_filename(char *filename);
|
||||
int parse_stream_name(char *filename, char **stream_name, int *s_type);
|
||||
char *convert_to_nt_pathname(char *filename, char *sharepath);
|
||||
int get_nlink(struct kstat *st);
|
||||
void ksmbd_conv_path_to_unix(char *path);
|
||||
void ksmbd_strip_last_slash(char *path);
|
||||
char *ksmbd_conv_path_to_unix(char *path);
|
||||
void ksmbd_conv_path_to_windows(char *path);
|
||||
char *ksmbd_extract_sharename(char *treename);
|
||||
char *convert_to_unix_name(struct ksmbd_share_config *share, char *name);
|
||||
|
@ -634,7 +634,7 @@ static char *
|
||||
smb2_get_name(struct ksmbd_share_config *share, const char *src,
|
||||
const int maxlen, struct nls_table *local_nls)
|
||||
{
|
||||
char *name, *unixname;
|
||||
char *name, *norm_name, *unixname;
|
||||
|
||||
name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
|
||||
if (IS_ERR(name)) {
|
||||
@ -643,11 +643,15 @@ smb2_get_name(struct ksmbd_share_config *share, const char *src,
|
||||
}
|
||||
|
||||
/* change it to absolute unix name */
|
||||
ksmbd_conv_path_to_unix(name);
|
||||
ksmbd_strip_last_slash(name);
|
||||
|
||||
unixname = convert_to_unix_name(share, name);
|
||||
norm_name = ksmbd_conv_path_to_unix(name);
|
||||
if (IS_ERR(norm_name)) {
|
||||
kfree(name);
|
||||
return norm_name;
|
||||
}
|
||||
kfree(name);
|
||||
|
||||
unixname = convert_to_unix_name(share, norm_name);
|
||||
kfree(norm_name);
|
||||
if (!unixname) {
|
||||
pr_err("can not convert absolute name\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -4041,6 +4045,10 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
path = &fp->filp->f_path;
|
||||
/* single EA entry is requested with given user.* name */
|
||||
if (req->InputBufferLength) {
|
||||
if (le32_to_cpu(req->InputBufferLength) <
|
||||
sizeof(struct smb2_ea_info_req))
|
||||
return -EINVAL;
|
||||
|
||||
ea_req = (struct smb2_ea_info_req *)req->Buffer;
|
||||
} else {
|
||||
/* need to send all EAs, if no specific EA is requested*/
|
||||
|
@ -20,7 +20,6 @@
|
||||
#define SUBMOD_NAME "smb_direct"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/rwlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/highmem.h>
|
||||
|
Loading…
Reference in New Issue
Block a user