Commit a3a78b63 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.20-rc2-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server fixes from Steve French:

 - important sparse file fix

 - allocation size fix

 - fix incorrect rc on bad share

 - share config fix

* tag '5.20-rc2-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: don't remove dos attribute xattr on O_TRUNC open
  ksmbd: remove unnecessary generic_fillattr in smb2_open
  ksmbd: request update to stale share config
  ksmbd: return STATUS_BAD_NETWORK_NAME error status if share is not configured
parents 963a70be 17661ecf
...@@ -349,6 +349,7 @@ enum KSMBD_TREE_CONN_STATUS { ...@@ -349,6 +349,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_SHARE_FLAG_STREAMS BIT(11) #define KSMBD_SHARE_FLAG_STREAMS BIT(11)
#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) #define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) #define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
#define KSMBD_SHARE_FLAG_UPDATE BIT(14)
/* /*
* Tree connect request flags. * Tree connect request flags.
...@@ -364,6 +365,7 @@ enum KSMBD_TREE_CONN_STATUS { ...@@ -364,6 +365,7 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1) #define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1)
#define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2) #define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2)
#define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3) #define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3)
#define KSMBD_TREE_CONN_FLAG_UPDATE BIT(4)
/* /*
* RPC over IPC. * RPC over IPC.
......
...@@ -51,12 +51,16 @@ static void kill_share(struct ksmbd_share_config *share) ...@@ -51,12 +51,16 @@ static void kill_share(struct ksmbd_share_config *share)
kfree(share); kfree(share);
} }
void __ksmbd_share_config_put(struct ksmbd_share_config *share) void ksmbd_share_config_del(struct ksmbd_share_config *share)
{ {
down_write(&shares_table_lock); down_write(&shares_table_lock);
hash_del(&share->hlist); hash_del(&share->hlist);
up_write(&shares_table_lock); up_write(&shares_table_lock);
}
void __ksmbd_share_config_put(struct ksmbd_share_config *share)
{
ksmbd_share_config_del(share);
kill_share(share); kill_share(share);
} }
......
...@@ -64,6 +64,7 @@ static inline int test_share_config_flag(struct ksmbd_share_config *share, ...@@ -64,6 +64,7 @@ static inline int test_share_config_flag(struct ksmbd_share_config *share,
return share->flags & flag; return share->flags & flag;
} }
void ksmbd_share_config_del(struct ksmbd_share_config *share);
void __ksmbd_share_config_put(struct ksmbd_share_config *share); void __ksmbd_share_config_put(struct ksmbd_share_config *share);
static inline void ksmbd_share_config_put(struct ksmbd_share_config *share) static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
......
...@@ -19,7 +19,7 @@ struct ksmbd_tree_conn_status ...@@ -19,7 +19,7 @@ struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
char *share_name) char *share_name)
{ {
struct ksmbd_tree_conn_status status = {-EINVAL, NULL}; struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
struct ksmbd_tree_connect_response *resp = NULL; struct ksmbd_tree_connect_response *resp = NULL;
struct ksmbd_share_config *sc; struct ksmbd_share_config *sc;
struct ksmbd_tree_connect *tree_conn = NULL; struct ksmbd_tree_connect *tree_conn = NULL;
...@@ -57,6 +57,20 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ...@@ -57,6 +57,20 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
goto out_error; goto out_error;
tree_conn->flags = resp->connection_flags; tree_conn->flags = resp->connection_flags;
if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
struct ksmbd_share_config *new_sc;
ksmbd_share_config_del(sc);
new_sc = ksmbd_share_config_get(share_name);
if (!new_sc) {
pr_err("Failed to update stale share config\n");
status.ret = -ESTALE;
goto out_error;
}
ksmbd_share_config_put(sc);
sc = new_sc;
}
tree_conn->user = sess->user; tree_conn->user = sess->user;
tree_conn->share_conf = sc; tree_conn->share_conf = sc;
status.tree_conn = tree_conn; status.tree_conn = tree_conn;
......
...@@ -1944,8 +1944,10 @@ int smb2_tree_connect(struct ksmbd_work *work) ...@@ -1944,8 +1944,10 @@ int smb2_tree_connect(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_SUCCESS; rsp->hdr.Status = STATUS_SUCCESS;
rc = 0; rc = 0;
break; break;
case -ESTALE:
case -ENOENT:
case KSMBD_TREE_CONN_STATUS_NO_SHARE: case KSMBD_TREE_CONN_STATUS_NO_SHARE:
rsp->hdr.Status = STATUS_BAD_NETWORK_PATH; rsp->hdr.Status = STATUS_BAD_NETWORK_NAME;
break; break;
case -ENOMEM: case -ENOMEM:
case KSMBD_TREE_CONN_STATUS_NOMEM: case KSMBD_TREE_CONN_STATUS_NOMEM:
...@@ -2328,15 +2330,15 @@ static int smb2_remove_smb_xattrs(struct path *path) ...@@ -2328,15 +2330,15 @@ static int smb2_remove_smb_xattrs(struct path *path)
name += strlen(name) + 1) { name += strlen(name) + 1) {
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name)); ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
strncmp(&name[XATTR_USER_PREFIX_LEN], DOS_ATTRIBUTE_PREFIX, !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
DOS_ATTRIBUTE_PREFIX_LEN) && STREAM_PREFIX_LEN)) {
strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) err = ksmbd_vfs_remove_xattr(user_ns, path->dentry,
continue; name);
if (err)
err = ksmbd_vfs_remove_xattr(user_ns, path->dentry, name); ksmbd_debug(SMB, "remove xattr failed : %s\n",
if (err) name);
ksmbd_debug(SMB, "remove xattr failed : %s\n", name); }
} }
out: out:
kvfree(xattr_list); kvfree(xattr_list);
...@@ -3042,12 +3044,6 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3042,12 +3044,6 @@ int smb2_open(struct ksmbd_work *work)
list_add(&fp->node, &fp->f_ci->m_fp_list); list_add(&fp->node, &fp->f_ci->m_fp_list);
write_unlock(&fp->f_ci->m_lock); write_unlock(&fp->f_ci->m_lock);
rc = ksmbd_vfs_getattr(&path, &stat);
if (rc) {
generic_fillattr(user_ns, d_inode(path.dentry), &stat);
rc = 0;
}
/* Check delete pending among previous fp before oplock break */ /* Check delete pending among previous fp before oplock break */
if (ksmbd_inode_pending_delete(fp)) { if (ksmbd_inode_pending_delete(fp)) {
rc = -EBUSY; rc = -EBUSY;
...@@ -3134,6 +3130,10 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3134,6 +3130,10 @@ int smb2_open(struct ksmbd_work *work)
} }
} }
rc = ksmbd_vfs_getattr(&path, &stat);
if (rc)
goto err_out;
if (stat.result_mask & STATX_BTIME) if (stat.result_mask & STATX_BTIME)
fp->create_time = ksmbd_UnixTimeToNT(stat.btime); fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
else else
...@@ -3149,9 +3149,6 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3149,9 +3149,6 @@ int smb2_open(struct ksmbd_work *work)
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
generic_fillattr(user_ns, file_inode(fp->filp),
&stat);
rsp->StructureSize = cpu_to_le16(89); rsp->StructureSize = cpu_to_le16(89);
rcu_read_lock(); rcu_read_lock();
opinfo = rcu_dereference(fp->f_opinfo); opinfo = rcu_dereference(fp->f_opinfo);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment