1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
6 #include <linux/list.h>
7 #include <linux/jhash.h>
8 #include <linux/slab.h>
9 #include <linux/rwsem.h>
10 #include <linux/parser.h>
11 #include <linux/namei.h>
12 #include <linux/sched.h>
15 #include "share_config.h"
16 #include "user_config.h"
17 #include "user_session.h"
18 #include "../connection.h"
19 #include "../transport_ipc.h"
22 #define SHARE_HASH_BITS 3
23 static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
24 static DECLARE_RWSEM(shares_table_lock);
26 struct ksmbd_veto_pattern {
28 struct list_head list;
31 static unsigned int share_name_hash(const char *name)
33 return jhash(name, strlen(name), 0);
36 static void kill_share(struct ksmbd_share_config *share)
38 while (!list_empty(&share->veto_list)) {
39 struct ksmbd_veto_pattern *p;
41 p = list_entry(share->veto_list.next,
42 struct ksmbd_veto_pattern,
50 path_put(&share->vfs_path);
56 void ksmbd_share_config_del(struct ksmbd_share_config *share)
58 down_write(&shares_table_lock);
59 hash_del(&share->hlist);
60 up_write(&shares_table_lock);
63 void __ksmbd_share_config_put(struct ksmbd_share_config *share)
65 ksmbd_share_config_del(share);
69 static struct ksmbd_share_config *
70 __get_share_config(struct ksmbd_share_config *share)
72 if (!atomic_inc_not_zero(&share->refcount))
77 static struct ksmbd_share_config *__share_lookup(const char *name)
79 struct ksmbd_share_config *share;
80 unsigned int key = share_name_hash(name);
82 hash_for_each_possible(shares_table, share, hlist, key) {
83 if (!strcmp(name, share->name))
89 static int parse_veto_list(struct ksmbd_share_config *share,
98 while (veto_list_sz > 0) {
99 struct ksmbd_veto_pattern *p;
101 sz = strlen(veto_list);
105 p = kzalloc(sizeof(struct ksmbd_veto_pattern), KSMBD_DEFAULT_GFP);
109 p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
115 list_add(&p->list, &share->veto_list);
118 veto_list_sz -= (sz + 1);
124 static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
127 struct ksmbd_share_config_response *resp;
128 struct ksmbd_share_config *share = NULL;
129 struct ksmbd_share_config *lookup;
130 struct unicode_map *um = work->conn->um;
133 resp = ksmbd_ipc_share_config_request(name);
137 if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
140 if (*resp->share_name) {
144 cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
145 if (IS_ERR(cf_resp_name))
147 equal = !strcmp(cf_resp_name, name);
153 share = kzalloc(sizeof(struct ksmbd_share_config), KSMBD_DEFAULT_GFP);
157 share->flags = resp->flags;
158 atomic_set(&share->refcount, 1);
159 INIT_LIST_HEAD(&share->veto_list);
160 share->name = kstrdup(name, KSMBD_DEFAULT_GFP);
162 if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
163 int path_len = PATH_MAX;
165 if (resp->payload_sz)
166 path_len = resp->payload_sz - resp->veto_list_sz;
168 share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
171 share->path_sz = strlen(share->path);
172 while (share->path_sz > 1 &&
173 share->path[share->path_sz - 1] == '/')
174 share->path[--share->path_sz] = '\0';
176 share->create_mask = resp->create_mask;
177 share->directory_mask = resp->directory_mask;
178 share->force_create_mode = resp->force_create_mode;
179 share->force_directory_mode = resp->force_directory_mode;
180 share->force_uid = resp->force_uid;
181 share->force_gid = resp->force_gid;
182 ret = parse_veto_list(share,
183 KSMBD_SHARE_CONFIG_VETO_LIST(resp),
185 if (!ret && share->path) {
186 if (__ksmbd_override_fsids(work, share)) {
192 ret = kern_path(share->path, 0, &share->vfs_path);
193 ksmbd_revert_fsids(work);
195 ksmbd_debug(SMB, "failed to access '%s'\n",
197 /* Avoid put_path() */
202 if (ret || !share->name) {
209 down_write(&shares_table_lock);
210 lookup = __share_lookup(name);
212 lookup = __get_share_config(lookup);
214 hash_add(shares_table, &share->hlist, share_name_hash(name));
219 up_write(&shares_table_lock);
226 struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work,
229 struct ksmbd_share_config *share;
231 down_read(&shares_table_lock);
232 share = __share_lookup(name);
234 share = __get_share_config(share);
235 up_read(&shares_table_lock);
239 return share_config_request(work, name);
242 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
243 const char *filename)
245 struct ksmbd_veto_pattern *p;
247 list_for_each_entry(p, &share->veto_list, list) {
248 if (match_wildcard(p->pattern, filename))