]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ksmbd: override fsids for share path check
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 4 Aug 2024 23:56:18 +0000 (08:56 +0900)
committerSteve French <stfrench@microsoft.com>
Fri, 9 Aug 2024 03:54:09 +0000 (22:54 -0500)
Sangsoo reported that a DAC denial error occurred when accessing
files through the ksmbd thread. This patch override fsids for share
path check.

Reported-by: Sangsoo Lee <constant.lee@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/mgmt/share_config.c
fs/smb/server/mgmt/share_config.h
fs/smb/server/mgmt/tree_connect.c
fs/smb/server/mgmt/tree_connect.h
fs/smb/server/smb2pdu.c
fs/smb/server/smb_common.c
fs/smb/server/smb_common.h

index e0a6b758094fc57c5fd47d0be2ab9f4d1e94ee70..d8d03070ae44b46dab1505227f617218d09562e2 100644 (file)
@@ -15,6 +15,7 @@
 #include "share_config.h"
 #include "user_config.h"
 #include "user_session.h"
+#include "../connection.h"
 #include "../transport_ipc.h"
 #include "../misc.h"
 
@@ -120,12 +121,13 @@ static int parse_veto_list(struct ksmbd_share_config *share,
        return 0;
 }
 
-static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
                                                       const char *name)
 {
        struct ksmbd_share_config_response *resp;
        struct ksmbd_share_config *share = NULL;
        struct ksmbd_share_config *lookup;
+       struct unicode_map *um = work->conn->um;
        int ret;
 
        resp = ksmbd_ipc_share_config_request(name);
@@ -181,7 +183,14 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
                                      KSMBD_SHARE_CONFIG_VETO_LIST(resp),
                                      resp->veto_list_sz);
                if (!ret && share->path) {
+                       if (__ksmbd_override_fsids(work, share)) {
+                               kill_share(share);
+                               share = NULL;
+                               goto out;
+                       }
+
                        ret = kern_path(share->path, 0, &share->vfs_path);
+                       ksmbd_revert_fsids(work);
                        if (ret) {
                                ksmbd_debug(SMB, "failed to access '%s'\n",
                                            share->path);
@@ -214,7 +223,7 @@ out:
        return share;
 }
 
-struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work,
                                                  const char *name)
 {
        struct ksmbd_share_config *share;
@@ -227,7 +236,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
 
        if (share)
                return share;
-       return share_config_request(um, name);
+       return share_config_request(work, name);
 }
 
 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
index 5f591751b92365eac17d7e391ccdd57bc0a2e9b6..d4ac2dd4de204053e62634a2149fc588b9fad77f 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/path.h>
 #include <linux/unicode.h>
 
+struct ksmbd_work;
+
 struct ksmbd_share_config {
        char                    *name;
        char                    *path;
@@ -68,7 +70,7 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
        __ksmbd_share_config_put(share);
 }
 
-struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work,
                                                  const char *name);
 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
                               const char *filename);
index d2c81a8a11dda10ef710bc97e1c059073fddb700..94a52a75014a4384fb80fbc461f3f558341c4f55 100644 (file)
 #include "user_session.h"
 
 struct ksmbd_tree_conn_status
-ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
-                       const char *share_name)
+ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
 {
        struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
        struct ksmbd_tree_connect_response *resp = NULL;
        struct ksmbd_share_config *sc;
        struct ksmbd_tree_connect *tree_conn = NULL;
        struct sockaddr *peer_addr;
+       struct ksmbd_conn *conn = work->conn;
+       struct ksmbd_session *sess = work->sess;
        int ret;
 
-       sc = ksmbd_share_config_get(conn->um, share_name);
+       sc = ksmbd_share_config_get(work, share_name);
        if (!sc)
                return status;
 
@@ -61,7 +62,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                struct ksmbd_share_config *new_sc;
 
                ksmbd_share_config_del(sc);
-               new_sc = ksmbd_share_config_get(conn->um, share_name);
+               new_sc = ksmbd_share_config_get(work, share_name);
                if (!new_sc) {
                        pr_err("Failed to update stale share config\n");
                        status.ret = -ESTALE;
index 6377a70b811c8993575d96889a8c2ef5f2fada2c..a42cdd0510411437fe074ee3359a648496a36b13 100644 (file)
@@ -13,6 +13,7 @@
 struct ksmbd_share_config;
 struct ksmbd_user;
 struct ksmbd_conn;
+struct ksmbd_work;
 
 enum {
        TREE_NEW = 0,
@@ -50,8 +51,7 @@ static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn,
 struct ksmbd_session;
 
 struct ksmbd_tree_conn_status
-ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
-                       const char *share_name);
+ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name);
 void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon);
 
 int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
index 37a39ab4ee6543fbec2adb6dcb5fdfef93492e8d..54154d36ea2f81005736a36cd68388055948dc14 100644 (file)
@@ -1955,7 +1955,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
        ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n",
                    name, treename);
 
-       status = ksmbd_tree_conn_connect(conn, sess, name);
+       status = ksmbd_tree_conn_connect(work, name);
        if (status.ret == KSMBD_TREE_CONN_STATUS_OK)
                rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id);
        else
index 474dadf6b7b8bc51b3bfa94c6d29f02621f21cd5..13818ecb6e1b2fb24d8424d0bc70083b810adfe0 100644 (file)
@@ -732,10 +732,10 @@ bool is_asterisk(char *p)
        return p && p[0] == '*';
 }
 
-int ksmbd_override_fsids(struct ksmbd_work *work)
+int __ksmbd_override_fsids(struct ksmbd_work *work,
+               struct ksmbd_share_config *share)
 {
        struct ksmbd_session *sess = work->sess;
-       struct ksmbd_share_config *share = work->tcon->share_conf;
        struct cred *cred;
        struct group_info *gi;
        unsigned int uid;
@@ -775,6 +775,11 @@ int ksmbd_override_fsids(struct ksmbd_work *work)
        return 0;
 }
 
+int ksmbd_override_fsids(struct ksmbd_work *work)
+{
+       return __ksmbd_override_fsids(work, work->tcon->share_conf);
+}
+
 void ksmbd_revert_fsids(struct ksmbd_work *work)
 {
        const struct cred *cred;
index f1092519c0c288223b1ad7d2e66e9545fc5bcac3..4a3148b0167f5446c98fcc99028b14cada97b1a0 100644 (file)
@@ -447,6 +447,8 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn,
 int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command);
 
 int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp);
+int __ksmbd_override_fsids(struct ksmbd_work *work,
+                          struct ksmbd_share_config *share);
 int ksmbd_override_fsids(struct ksmbd_work *work);
 void ksmbd_revert_fsids(struct ksmbd_work *work);