Skip to content

Commit

Permalink
Merge tag '5.15-rc2-ksmbd-fixes' of git://git.samba.org/ksmbd
Browse files Browse the repository at this point in the history
Pull ksmbd fixes from Steve French:
 "Five fixes for the ksmbd kernel server, including three security
  fixes:

   - remove follow symlinks support

   - use LOOKUP_BENEATH to prevent out of share access

   - SMB3 compounding security fix

   - fix for returning the default streams correctly, fixing a bug when
     writing ppt or doc files from some clients

   - logging more clearly that ksmbd is experimental (at module load
     time)"

* tag '5.15-rc2-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: use LOOKUP_BENEATH to prevent the out of share access
  ksmbd: remove follow symlinks support
  ksmbd: check protocol id in ksmbd_verify_smb_message()
  ksmbd: add default data stream name in FILE_STREAM_INFORMATION
  ksmbd: log that server is experimental at module load
  • Loading branch information
torvalds committed Sep 26, 2021
2 parents 996148e + 265fd19 commit 5e5d759
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 260 deletions.
100 changes: 19 additions & 81 deletions fs/ksmbd/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,25 +158,21 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
* Return : windows path string or error
*/

char *convert_to_nt_pathname(char *filename, char *sharepath)
char *convert_to_nt_pathname(char *filename)
{
char *ab_pathname;
int len, name_len;

name_len = strlen(filename);
ab_pathname = kmalloc(name_len, GFP_KERNEL);
if (!ab_pathname)
return NULL;

ab_pathname[0] = '\\';
ab_pathname[1] = '\0';
if (strlen(filename) == 0) {
ab_pathname = kmalloc(2, GFP_KERNEL);
ab_pathname[0] = '\\';
ab_pathname[1] = '\0';
} else {
ab_pathname = kstrdup(filename, GFP_KERNEL);
if (!ab_pathname)
return NULL;

len = strlen(sharepath);
if (!strncmp(filename, sharepath, len) && name_len != len) {
strscpy(ab_pathname, &filename[len], name_len);
ksmbd_conv_path_to_windows(ab_pathname);
}

return ab_pathname;
}

Expand All @@ -191,77 +187,19 @@ int get_nlink(struct kstat *st)
return nlink;
}

char *ksmbd_conv_path_to_unix(char *path)
void 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);

out_path = kzalloc(path_len + 2, GFP_KERNEL);
if (!out_path)
return ERR_PTR(-ENOMEM);
out_path_len = 0;
out_next = out_path;

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);
void ksmbd_strip_last_slash(char *path)
{
int len = strlen(path);

if (out_path_len > 0)
out_path[out_path_len-1] = '\0';
path[path_len] = '\0';
return out_path;
while (len && path[len - 1] == '/') {
path[len - 1] = '\0';
len--;
}
}

void ksmbd_conv_path_to_windows(char *path)
Expand Down Expand Up @@ -298,7 +236,7 @@ char *ksmbd_extract_sharename(char *treename)
*
* Return: converted name on success, otherwise NULL
*/
char *convert_to_unix_name(struct ksmbd_share_config *share, char *name)
char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
{
int no_slash = 0, name_len, path_len;
char *new_name;
Expand Down
7 changes: 4 additions & 3 deletions fs/ksmbd/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ struct ksmbd_file;
int match_pattern(const char *str, size_t len, const char *pattern);
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);
char *convert_to_nt_pathname(char *filename);
int get_nlink(struct kstat *st);
char *ksmbd_conv_path_to_unix(char *path);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(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);
char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);

#define KSMBD_DIR_INFO_ALIGNMENT 8
struct ksmbd_dir_info;
Expand Down
3 changes: 3 additions & 0 deletions fs/ksmbd/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,9 @@ static int __init ksmbd_server_init(void)
ret = ksmbd_workqueue_init();
if (ret)
goto err_crypto_destroy;

pr_warn_once("The ksmbd server is experimental, use at your own risk.\n");

return 0;

err_crypto_destroy:
Expand Down
Loading

0 comments on commit 5e5d759

Please sign in to comment.