mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
6 ksmbd SMB3 server fixes, most also for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmgBxEoACgkQiiy9cAdy T1FYlwv/RmcWbI7IwsdvMQTRxSAJgbrRbLNjW3qTz0bCeccRgZGPDJgxIcaOwZqU LJcGMgr+ZxC3KBAh1xOy5F/88kqV6GnOsS7010QklWELymvbndf61g31CR7yGz8a Y2KIGVs3NVCmZ12iga6A+aUWZeWtYcXIDtkDM1ayROo4WXTROqw1EaTvyLSDVYuj fCQTRDKEUfEWwjO0Fw5G5yi9v5tEBiphX3/IvJTum6it0Xw9bycUG926Lf42N/uB /9JjDVWrkj8nnkjIU5/4ioI/adtC+/I383/by+PH9pq+QjlTtoK+UhvpY5aiHy5S dPsIlLe0Xevmxs9e40L3kbMwle6hlQgzLu2uvMVTyRwNlv4aoNteBWvA4EpfHo3O p/0jG19217DiA/pQEAXs9YH133sdqR3xlitgmyUy6xocMxcQEp1qV9dPm4EA+y+X /5FgtRoq91C2yY7zvdRPd1+dp1nKAJssU538hIUa7T5MnFir7I8bhT9qkBR6xEPe dNULAc3d =d3g0 -----END PGP SIGNATURE----- Merge tag 'v6.15-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd Pull smb server fixes from Steve French: - Fix integer overflow in server disconnect deadtime calculation - Three fixes for potential use after frees: one for oplocks, and one for leases and one for kerberos authentication - Fix to prevent attempted write to directory - Fix locking warning for durable scavenger thread * tag 'v6.15-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: Prevent integer overflow in calculation of deadtime ksmbd: fix the warning from __kernel_write_iter ksmbd: fix use-after-free in smb_break_all_levII_oplock() ksmbd: fix use-after-free in __smb2_lease_break_noti() ksmbd: fix WARNING "do not call blocking ops when !TASK_RUNNING" ksmbd: Fix dangling pointer in krb_authenticate
This commit is contained in:
commit
7e74f756f5
@ -39,8 +39,10 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
|
||||
xa_destroy(&conn->sessions);
|
||||
kvfree(conn->request_buf);
|
||||
kfree(conn->preauth_info);
|
||||
if (atomic_dec_and_test(&conn->refcnt))
|
||||
if (atomic_dec_and_test(&conn->refcnt)) {
|
||||
ksmbd_free_transport(conn->transport);
|
||||
kfree(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,14 +129,6 @@ static void free_opinfo(struct oplock_info *opinfo)
|
||||
kfree(opinfo);
|
||||
}
|
||||
|
||||
static inline void opinfo_free_rcu(struct rcu_head *rcu_head)
|
||||
{
|
||||
struct oplock_info *opinfo;
|
||||
|
||||
opinfo = container_of(rcu_head, struct oplock_info, rcu_head);
|
||||
free_opinfo(opinfo);
|
||||
}
|
||||
|
||||
struct oplock_info *opinfo_get(struct ksmbd_file *fp)
|
||||
{
|
||||
struct oplock_info *opinfo;
|
||||
@ -157,8 +149,8 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
|
||||
if (list_empty(&ci->m_op_list))
|
||||
return NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
|
||||
down_read(&ci->m_lock);
|
||||
opinfo = list_first_entry(&ci->m_op_list, struct oplock_info,
|
||||
op_entry);
|
||||
if (opinfo) {
|
||||
if (opinfo->conn == NULL ||
|
||||
@ -171,8 +163,7 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
up_read(&ci->m_lock);
|
||||
|
||||
return opinfo;
|
||||
}
|
||||
@ -185,7 +176,7 @@ void opinfo_put(struct oplock_info *opinfo)
|
||||
if (!atomic_dec_and_test(&opinfo->refcount))
|
||||
return;
|
||||
|
||||
call_rcu(&opinfo->rcu_head, opinfo_free_rcu);
|
||||
free_opinfo(opinfo);
|
||||
}
|
||||
|
||||
static void opinfo_add(struct oplock_info *opinfo)
|
||||
@ -193,7 +184,7 @@ static void opinfo_add(struct oplock_info *opinfo)
|
||||
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
|
||||
|
||||
down_write(&ci->m_lock);
|
||||
list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
|
||||
list_add(&opinfo->op_entry, &ci->m_op_list);
|
||||
up_write(&ci->m_lock);
|
||||
}
|
||||
|
||||
@ -207,7 +198,7 @@ static void opinfo_del(struct oplock_info *opinfo)
|
||||
write_unlock(&lease_list_lock);
|
||||
}
|
||||
down_write(&ci->m_lock);
|
||||
list_del_rcu(&opinfo->op_entry);
|
||||
list_del(&opinfo->op_entry);
|
||||
up_write(&ci->m_lock);
|
||||
}
|
||||
|
||||
@ -1347,8 +1338,8 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
ci = fp->f_ci;
|
||||
op = opinfo_get(fp);
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
|
||||
down_read(&ci->m_lock);
|
||||
list_for_each_entry(brk_op, &ci->m_op_list, op_entry) {
|
||||
if (brk_op->conn == NULL)
|
||||
continue;
|
||||
|
||||
@ -1358,7 +1349,6 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
if (ksmbd_conn_releasing(brk_op->conn))
|
||||
continue;
|
||||
|
||||
rcu_read_unlock();
|
||||
if (brk_op->is_lease && (brk_op->o_lease->state &
|
||||
(~(SMB2_LEASE_READ_CACHING_LE |
|
||||
SMB2_LEASE_HANDLE_CACHING_LE)))) {
|
||||
@ -1388,9 +1378,8 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE, NULL);
|
||||
next:
|
||||
opinfo_put(brk_op);
|
||||
rcu_read_lock();
|
||||
}
|
||||
rcu_read_unlock();
|
||||
up_read(&ci->m_lock);
|
||||
|
||||
if (op)
|
||||
opinfo_put(op);
|
||||
|
@ -71,7 +71,6 @@ struct oplock_info {
|
||||
struct list_head lease_entry;
|
||||
wait_queue_head_t oplock_q; /* Other server threads */
|
||||
wait_queue_head_t oplock_brk; /* oplock breaking wait */
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
struct lease_break_info {
|
||||
|
@ -1602,8 +1602,10 @@ static int krb5_authenticate(struct ksmbd_work *work,
|
||||
if (prev_sess_id && prev_sess_id != sess->id)
|
||||
destroy_previous_session(conn, sess->user, prev_sess_id);
|
||||
|
||||
if (sess->state == SMB2_SESSION_VALID)
|
||||
if (sess->state == SMB2_SESSION_VALID) {
|
||||
ksmbd_free_user(sess->user);
|
||||
sess->user = NULL;
|
||||
}
|
||||
|
||||
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
|
||||
out_blob, &out_len);
|
||||
|
@ -310,7 +310,11 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
|
||||
server_conf.signing = req->signing;
|
||||
server_conf.tcp_port = req->tcp_port;
|
||||
server_conf.ipc_timeout = req->ipc_timeout * HZ;
|
||||
server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
|
||||
if (check_mul_overflow(req->deadtime, SMB_ECHO_INTERVAL,
|
||||
&server_conf.deadtime)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
server_conf.share_fake_fscaps = req->share_fake_fscaps;
|
||||
ksmbd_init_domain(req->sub_auth);
|
||||
|
||||
@ -337,6 +341,7 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
|
||||
server_conf.bind_interfaces_only = req->bind_interfaces_only;
|
||||
ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
|
||||
req->ifc_list_sz);
|
||||
out:
|
||||
if (ret) {
|
||||
pr_err("Server configuration error: %s %s %s\n",
|
||||
req->netbios_name, req->server_string,
|
||||
|
@ -93,15 +93,19 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
|
||||
return t;
|
||||
}
|
||||
|
||||
void ksmbd_free_transport(struct ksmbd_transport *kt)
|
||||
{
|
||||
struct tcp_transport *t = TCP_TRANS(kt);
|
||||
|
||||
sock_release(t->sock);
|
||||
kfree(t->iov);
|
||||
kfree(t);
|
||||
}
|
||||
|
||||
static void free_transport(struct tcp_transport *t)
|
||||
{
|
||||
kernel_sock_shutdown(t->sock, SHUT_RDWR);
|
||||
sock_release(t->sock);
|
||||
t->sock = NULL;
|
||||
|
||||
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
|
||||
kfree(t->iov);
|
||||
kfree(t);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
|
||||
struct interface *ksmbd_find_netdev_name_iface_list(char *netdev_name);
|
||||
void ksmbd_free_transport(struct ksmbd_transport *kt);
|
||||
int ksmbd_tcp_init(void);
|
||||
void ksmbd_tcp_destroy(void);
|
||||
|
||||
|
@ -479,7 +479,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
int err = 0;
|
||||
|
||||
if (work->conn->connection_type) {
|
||||
if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
|
||||
if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) ||
|
||||
S_ISDIR(file_inode(fp->filp)->i_mode)) {
|
||||
pr_err("no right to write(%pD)\n", fp->filp);
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
|
@ -713,12 +713,8 @@ static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
|
||||
|
||||
static bool ksmbd_durable_scavenger_alive(void)
|
||||
{
|
||||
mutex_lock(&durable_scavenger_lock);
|
||||
if (!durable_scavenger_running) {
|
||||
mutex_unlock(&durable_scavenger_lock);
|
||||
if (!durable_scavenger_running)
|
||||
return false;
|
||||
}
|
||||
mutex_unlock(&durable_scavenger_lock);
|
||||
|
||||
if (kthread_should_stop())
|
||||
return false;
|
||||
@ -799,9 +795,7 @@ static int ksmbd_durable_scavenger(void *dummy)
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&durable_scavenger_lock);
|
||||
durable_scavenger_running = false;
|
||||
mutex_unlock(&durable_scavenger_lock);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user