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 "../transport_ipc.h"
20 #define SHARE_HASH_BITS 3
21 static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
22 static DECLARE_RWSEM(shares_table_lock);
24 struct ksmbd_veto_pattern {
26 struct list_head list;
29 static unsigned int share_name_hash(char *name)
31 return jhash(name, strlen(name), 0);
34 static void kill_share(struct ksmbd_share_config *share)
36 while (!list_empty(&share->veto_list)) {
37 struct ksmbd_veto_pattern *p;
39 p = list_entry(share->veto_list.next,
40 struct ksmbd_veto_pattern,
48 path_put(&share->vfs_path);
54 void ksmbd_share_config_del(struct ksmbd_share_config *share)
56 down_write(&shares_table_lock);
57 hash_del(&share->hlist);
58 up_write(&shares_table_lock);
61 void __ksmbd_share_config_put(struct ksmbd_share_config *share)
63 ksmbd_share_config_del(share);
67 static struct ksmbd_share_config *
68 __get_share_config(struct ksmbd_share_config *share)
70 if (!atomic_inc_not_zero(&share->refcount))
75 static struct ksmbd_share_config *__share_lookup(char *name)
77 struct ksmbd_share_config *share;
78 unsigned int key = share_name_hash(name);
80 hash_for_each_possible(shares_table, share, hlist, key) {
81 if (!strcmp(name, share->name))
87 static int parse_veto_list(struct ksmbd_share_config *share,
96 while (veto_list_sz > 0) {
97 struct ksmbd_veto_pattern *p;
99 sz = strlen(veto_list);
103 p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
107 p->pattern = kstrdup(veto_list, GFP_KERNEL);
113 list_add(&p->list, &share->veto_list);
116 veto_list_sz -= (sz + 1);
122 static struct ksmbd_share_config *share_config_request(char *name)
124 struct ksmbd_share_config_response *resp;
125 struct ksmbd_share_config *share = NULL;
126 struct ksmbd_share_config *lookup;
129 resp = ksmbd_ipc_share_config_request(name);
133 if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
136 share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
140 share->flags = resp->flags;
141 atomic_set(&share->refcount, 1);
142 INIT_LIST_HEAD(&share->veto_list);
143 share->name = kstrdup(name, GFP_KERNEL);
145 if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
146 share->path = kstrdup(ksmbd_share_config_path(resp),
149 share->path_sz = strlen(share->path);
150 share->create_mask = resp->create_mask;
151 share->directory_mask = resp->directory_mask;
152 share->force_create_mode = resp->force_create_mode;
153 share->force_directory_mode = resp->force_directory_mode;
154 share->force_uid = resp->force_uid;
155 share->force_gid = resp->force_gid;
156 ret = parse_veto_list(share,
157 KSMBD_SHARE_CONFIG_VETO_LIST(resp),
159 if (!ret && share->path) {
160 ret = kern_path(share->path, 0, &share->vfs_path);
162 ksmbd_debug(SMB, "failed to access '%s'\n",
164 /* Avoid put_path() */
169 if (ret || !share->name) {
176 down_write(&shares_table_lock);
177 lookup = __share_lookup(name);
179 lookup = __get_share_config(lookup);
181 hash_add(shares_table, &share->hlist, share_name_hash(name));
186 up_write(&shares_table_lock);
193 static void strtolower(char *share_name)
195 while (*share_name) {
196 *share_name = tolower(*share_name);
201 struct ksmbd_share_config *ksmbd_share_config_get(char *name)
203 struct ksmbd_share_config *share;
207 down_read(&shares_table_lock);
208 share = __share_lookup(name);
210 share = __get_share_config(share);
211 up_read(&shares_table_lock);
215 return share_config_request(name);
218 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
219 const char *filename)
221 struct ksmbd_veto_pattern *p;
223 list_for_each_entry(p, &share->veto_list, list) {
224 if (match_wildcard(p->pattern, filename))