Skip to content

Commit

Permalink
Merge tag 'v6.15-rc5-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Browse files Browse the repository at this point in the history
Pull smb server fixes from Steve French:

 - Fix UAF closing file table (e.g. in tree disconnect)

 - Fix potential out of bounds write

 - Fix potential memory leak parsing lease state in open

 - Fix oops in rename with empty target

* tag 'v6.15-rc5-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: Fix UAF in __close_file_table_ids
  ksmbd: prevent out-of-bounds stream writes by validating *pos
  ksmbd: fix memory leak in parse_lease_state()
  ksmbd: prevent rename with empty string
  • Loading branch information
Linus Torvalds committed May 8, 2025
2 parents d76bb1e + 36991c1 commit 80ae5fb
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 9 deletions.
7 changes: 5 additions & 2 deletions fs/smb/server/oplock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)

if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) <
sizeof(struct create_lease_v2) - 4)
return NULL;
goto err_out;

memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
Expand All @@ -1512,7 +1512,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)

if (le16_to_cpu(cc->DataOffset) + le32_to_cpu(cc->DataLength) <
sizeof(struct create_lease))
return NULL;
goto err_out;

memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
Expand All @@ -1521,6 +1521,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
lreq->version = 1;
}
return lreq;
err_out:
kfree(lreq);
return NULL;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions fs/smb/server/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,11 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
return name;
}

if (*name == '\0') {
kfree(name);
return ERR_PTR(-EINVAL);
}

if (*name == '\\') {
pr_err("not allow directory name included leading slash\n");
kfree(name);
Expand Down
7 changes: 7 additions & 0 deletions fs/smb/server/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,13 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
goto out;
}

if (v_len <= *pos) {
pr_err("stream write position %lld is out of bounds (stream length: %zd)\n",
*pos, v_len);
err = -EINVAL;
goto out;
}

if (v_len < size) {
wbuf = kvzalloc(size, KSMBD_DEFAULT_GFP);
if (!wbuf) {
Expand Down
33 changes: 26 additions & 7 deletions fs/smb/server/vfs_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,21 +661,40 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
bool (*skip)(struct ksmbd_tree_connect *tcon,
struct ksmbd_file *fp))
{
unsigned int id;
struct ksmbd_file *fp;
int num = 0;
struct ksmbd_file *fp;
unsigned int id = 0;
int num = 0;

while (1) {
write_lock(&ft->lock);
fp = idr_get_next(ft->idr, &id);
if (!fp) {
write_unlock(&ft->lock);
break;
}

idr_for_each_entry(ft->idr, fp, id) {
if (skip(tcon, fp))
if (skip(tcon, fp) ||
!atomic_dec_and_test(&fp->refcount)) {
id++;
write_unlock(&ft->lock);
continue;
}

set_close_state_blocked_works(fp);
idr_remove(ft->idr, fp->volatile_id);
fp->volatile_id = KSMBD_NO_FID;
write_unlock(&ft->lock);

down_write(&fp->f_ci->m_lock);
list_del_init(&fp->node);
up_write(&fp->f_ci->m_lock);

if (!atomic_dec_and_test(&fp->refcount))
continue;
__ksmbd_close_fd(ft, fp);

num++;
id++;
}

return num;
}

Expand Down

0 comments on commit 80ae5fb

Please sign in to comment.