cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tree_connect.c (2787B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
      4 */
      5
      6#include <linux/list.h>
      7#include <linux/slab.h>
      8#include <linux/xarray.h>
      9
     10#include "../transport_ipc.h"
     11#include "../connection.h"
     12
     13#include "tree_connect.h"
     14#include "user_config.h"
     15#include "share_config.h"
     16#include "user_session.h"
     17
     18struct ksmbd_tree_conn_status
     19ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name)
     20{
     21	struct ksmbd_tree_conn_status status = {-EINVAL, NULL};
     22	struct ksmbd_tree_connect_response *resp = NULL;
     23	struct ksmbd_share_config *sc;
     24	struct ksmbd_tree_connect *tree_conn = NULL;
     25	struct sockaddr *peer_addr;
     26	int ret;
     27
     28	sc = ksmbd_share_config_get(share_name);
     29	if (!sc)
     30		return status;
     31
     32	tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
     33	if (!tree_conn) {
     34		status.ret = -ENOMEM;
     35		goto out_error;
     36	}
     37
     38	tree_conn->id = ksmbd_acquire_tree_conn_id(sess);
     39	if (tree_conn->id < 0) {
     40		status.ret = -EINVAL;
     41		goto out_error;
     42	}
     43
     44	peer_addr = KSMBD_TCP_PEER_SOCKADDR(sess->conn);
     45	resp = ksmbd_ipc_tree_connect_request(sess,
     46					      sc,
     47					      tree_conn,
     48					      peer_addr);
     49	if (!resp) {
     50		status.ret = -EINVAL;
     51		goto out_error;
     52	}
     53
     54	status.ret = resp->status;
     55	if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
     56		goto out_error;
     57
     58	tree_conn->flags = resp->connection_flags;
     59	tree_conn->user = sess->user;
     60	tree_conn->share_conf = sc;
     61	status.tree_conn = tree_conn;
     62
     63	ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
     64			      GFP_KERNEL));
     65	if (ret) {
     66		status.ret = -ENOMEM;
     67		goto out_error;
     68	}
     69	kvfree(resp);
     70	return status;
     71
     72out_error:
     73	if (tree_conn)
     74		ksmbd_release_tree_conn_id(sess, tree_conn->id);
     75	ksmbd_share_config_put(sc);
     76	kfree(tree_conn);
     77	kvfree(resp);
     78	return status;
     79}
     80
     81int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
     82			       struct ksmbd_tree_connect *tree_conn)
     83{
     84	int ret;
     85
     86	ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
     87	ksmbd_release_tree_conn_id(sess, tree_conn->id);
     88	xa_erase(&sess->tree_conns, tree_conn->id);
     89	ksmbd_share_config_put(tree_conn->share_conf);
     90	kfree(tree_conn);
     91	return ret;
     92}
     93
     94struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
     95						  unsigned int id)
     96{
     97	return xa_load(&sess->tree_conns, id);
     98}
     99
    100struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
    101						 unsigned int id)
    102{
    103	struct ksmbd_tree_connect *tc;
    104
    105	tc = ksmbd_tree_conn_lookup(sess, id);
    106	if (tc)
    107		return tc->share_conf;
    108	return NULL;
    109}
    110
    111int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
    112{
    113	int ret = 0;
    114	struct ksmbd_tree_connect *tc;
    115	unsigned long id;
    116
    117	xa_for_each(&sess->tree_conns, id, tc)
    118		ret |= ksmbd_tree_conn_disconnect(sess, tc);
    119	xa_destroy(&sess->tree_conns);
    120	return ret;
    121}