brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · d8d0307 Raw
253 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.4 */5 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>13#include <linux/mm.h>14 15#include "share_config.h"16#include "user_config.h"17#include "user_session.h"18#include "../connection.h"19#include "../transport_ipc.h"20#include "../misc.h"21 22#define SHARE_HASH_BITS		323static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);24static DECLARE_RWSEM(shares_table_lock);25 26struct ksmbd_veto_pattern {27	char			*pattern;28	struct list_head	list;29};30 31static unsigned int share_name_hash(const char *name)32{33	return jhash(name, strlen(name), 0);34}35 36static void kill_share(struct ksmbd_share_config *share)37{38	while (!list_empty(&share->veto_list)) {39		struct ksmbd_veto_pattern *p;40 41		p = list_entry(share->veto_list.next,42			       struct ksmbd_veto_pattern,43			       list);44		list_del(&p->list);45		kfree(p->pattern);46		kfree(p);47	}48 49	if (share->path)50		path_put(&share->vfs_path);51	kfree(share->name);52	kfree(share->path);53	kfree(share);54}55 56void ksmbd_share_config_del(struct ksmbd_share_config *share)57{58	down_write(&shares_table_lock);59	hash_del(&share->hlist);60	up_write(&shares_table_lock);61}62 63void __ksmbd_share_config_put(struct ksmbd_share_config *share)64{65	ksmbd_share_config_del(share);66	kill_share(share);67}68 69static struct ksmbd_share_config *70__get_share_config(struct ksmbd_share_config *share)71{72	if (!atomic_inc_not_zero(&share->refcount))73		return NULL;74	return share;75}76 77static struct ksmbd_share_config *__share_lookup(const char *name)78{79	struct ksmbd_share_config *share;80	unsigned int key = share_name_hash(name);81 82	hash_for_each_possible(shares_table, share, hlist, key) {83		if (!strcmp(name, share->name))84			return share;85	}86	return NULL;87}88 89static int parse_veto_list(struct ksmbd_share_config *share,90			   char *veto_list,91			   int veto_list_sz)92{93	int sz = 0;94 95	if (!veto_list_sz)96		return 0;97 98	while (veto_list_sz > 0) {99		struct ksmbd_veto_pattern *p;100 101		sz = strlen(veto_list);102		if (!sz)103			break;104 105		p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);106		if (!p)107			return -ENOMEM;108 109		p->pattern = kstrdup(veto_list, GFP_KERNEL);110		if (!p->pattern) {111			kfree(p);112			return -ENOMEM;113		}114 115		list_add(&p->list, &share->veto_list);116 117		veto_list += sz + 1;118		veto_list_sz -= (sz + 1);119	}120 121	return 0;122}123 124static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,125						       const char *name)126{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;131	int ret;132 133	resp = ksmbd_ipc_share_config_request(name);134	if (!resp)135		return NULL;136 137	if (resp->flags == KSMBD_SHARE_FLAG_INVALID)138		goto out;139 140	if (*resp->share_name) {141		char *cf_resp_name;142		bool equal;143 144		cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);145		if (IS_ERR(cf_resp_name))146			goto out;147		equal = !strcmp(cf_resp_name, name);148		kfree(cf_resp_name);149		if (!equal)150			goto out;151	}152 153	share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);154	if (!share)155		goto out;156 157	share->flags = resp->flags;158	atomic_set(&share->refcount, 1);159	INIT_LIST_HEAD(&share->veto_list);160	share->name = kstrdup(name, GFP_KERNEL);161 162	if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {163		int path_len = PATH_MAX;164 165		if (resp->payload_sz)166			path_len = resp->payload_sz - resp->veto_list_sz;167 168		share->path = kstrndup(ksmbd_share_config_path(resp), path_len,169				      GFP_KERNEL);170		if (share->path) {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';175		}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),184				      resp->veto_list_sz);185		if (!ret && share->path) {186			if (__ksmbd_override_fsids(work, share)) {187				kill_share(share);188				share = NULL;189				goto out;190			}191 192			ret = kern_path(share->path, 0, &share->vfs_path);193			ksmbd_revert_fsids(work);194			if (ret) {195				ksmbd_debug(SMB, "failed to access '%s'\n",196					    share->path);197				/* Avoid put_path() */198				kfree(share->path);199				share->path = NULL;200			}201		}202		if (ret || !share->name) {203			kill_share(share);204			share = NULL;205			goto out;206		}207	}208 209	down_write(&shares_table_lock);210	lookup = __share_lookup(name);211	if (lookup)212		lookup = __get_share_config(lookup);213	if (!lookup) {214		hash_add(shares_table, &share->hlist, share_name_hash(name));215	} else {216		kill_share(share);217		share = lookup;218	}219	up_write(&shares_table_lock);220 221out:222	kvfree(resp);223	return share;224}225 226struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work,227						  const char *name)228{229	struct ksmbd_share_config *share;230 231	down_read(&shares_table_lock);232	share = __share_lookup(name);233	if (share)234		share = __get_share_config(share);235	up_read(&shares_table_lock);236 237	if (share)238		return share;239	return share_config_request(work, name);240}241 242bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,243			       const char *filename)244{245	struct ksmbd_veto_pattern *p;246 247	list_for_each_entry(p, &share->veto_list, list) {248		if (match_wildcard(p->pattern, filename))249			return true;250	}251	return false;252}253