Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  share_config.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */


#include <linux/list.h>
#include <linux/jhash.h>
#include <linux/slab.h>
#include <linux/rwsem.h>
#include <linux/parser.h>
#include <linux/namei.h>
#include <linux/sched.h>
#include <linux/mm.h>

#include "share_config.h"
#include "user_config.h"
#include "user_session.h"
#include "../connection.h"
#include "../transport_ipc.h"
#include "../misc.h"

#define SHARE_HASH_BITS  3
static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
static DECLARE_RWSEM(shares_table_lock);

struct ksmbd_veto_pattern {
 char   *pattern;
 struct list_head list;
};

static unsigned int share_name_hash(const char *name)
{
 return jhash(name, strlen(name), 0);
}

static void kill_share(struct ksmbd_share_config *share)
{
 while (!list_empty(&share->veto_list)) {
  struct ksmbd_veto_pattern *p;

  p = list_entry(share->veto_list.next,
          struct ksmbd_veto_pattern,
          list);
  list_del(&p->list);
  kfree(p->pattern);
  kfree(p);
 }

 if (share->path)
  path_put(&share->vfs_path);
 kfree(share->name);
 kfree(share->path);
 kfree(share);
}

void ksmbd_share_config_del(struct ksmbd_share_config *share)
{
 down_write(&shares_table_lock);
 hash_del(&share->hlist);
 up_write(&shares_table_lock);
}

void __ksmbd_share_config_put(struct ksmbd_share_config *share)
{
 ksmbd_share_config_del(share);
 kill_share(share);
}

static struct ksmbd_share_config *
__get_share_config(struct ksmbd_share_config *share)
{
 if (!atomic_inc_not_zero(&share->refcount))
  return NULL;
 return share;
}

static struct ksmbd_share_config *__share_lookup(const char *name)
{
 struct ksmbd_share_config *share;
 unsigned int key = share_name_hash(name);

 hash_for_each_possible(shares_table, share, hlist, key) {
  if (!strcmp(name, share->name))
   return share;
 }
 return NULL;
}

static int parse_veto_list(struct ksmbd_share_config *share,
      char *veto_list,
      int veto_list_sz)
{
 int sz = 0;

 if (!veto_list_sz)
  return 0;

 while (veto_list_sz > 0) {
  struct ksmbd_veto_pattern *p;

  sz = strlen(veto_list);
  if (!sz)
   break;

  p = kzalloc(sizeof(struct ksmbd_veto_pattern), KSMBD_DEFAULT_GFP);
  if (!p)
   return -ENOMEM;

  p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
  if (!p->pattern) {
   kfree(p);
   return -ENOMEM;
  }

  list_add(&p->list, &share->veto_list);

  veto_list += sz + 1;
  veto_list_sz -= (sz + 1);
 }

 return 0;
}

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);
 if (!resp)
  return NULL;

 if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
  goto out;

 if (*resp->share_name) {
  char *cf_resp_name;
  bool equal;

  cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
  if (IS_ERR(cf_resp_name))
   goto out;
  equal = !strcmp(cf_resp_name, name);
  kfree(cf_resp_name);
  if (!equal)
   goto out;
 }

 share = kzalloc(sizeof(struct ksmbd_share_config), KSMBD_DEFAULT_GFP);
 if (!share)
  goto out;

 share->flags = resp->flags;
 atomic_set(&share->refcount, 1);
 INIT_LIST_HEAD(&share->veto_list);
 share->name = kstrdup(name, KSMBD_DEFAULT_GFP);

 if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
  int path_len = PATH_MAX;

  if (resp->payload_sz)
   path_len = resp->payload_sz - resp->veto_list_sz;

  share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
          KSMBD_DEFAULT_GFP);
  if (share->path) {
   share->path_sz = strlen(share->path);
   while (share->path_sz > 1 &&
          share->path[share->path_sz - 1] == '/')
    share->path[--share->path_sz] = '\0';
  }
  share->create_mask = resp->create_mask;
  share->directory_mask = resp->directory_mask;
  share->force_create_mode = resp->force_create_mode;
  share->force_directory_mode = resp->force_directory_mode;
  share->force_uid = resp->force_uid;
  share->force_gid = resp->force_gid;
  ret = parse_veto_list(share,
          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);
    /* Avoid put_path() */
    kfree(share->path);
    share->path = NULL;
   }
  }
  if (ret || !share->name) {
   kill_share(share);
   share = NULL;
   goto out;
  }
 }

 down_write(&shares_table_lock);
 lookup = __share_lookup(name);
 if (lookup)
  lookup = __get_share_config(lookup);
 if (!lookup) {
  hash_add(shares_table, &share->hlist, share_name_hash(name));
 } else {
  kill_share(share);
  share = lookup;
 }
 up_write(&shares_table_lock);

out:
 kvfree(resp);
 return share;
}

struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work,
        const char *name)
{
 struct ksmbd_share_config *share;

 down_read(&shares_table_lock);
 share = __share_lookup(name);
 if (share)
  share = __get_share_config(share);
 up_read(&shares_table_lock);

 if (share)
  return share;
 return share_config_request(work, name);
}

bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
          const char *filename)
{
 struct ksmbd_veto_pattern *p;

 list_for_each_entry(p, &share->veto_list, list) {
  if (match_wildcard(p->pattern, filename))
   return true;
 }
 return false;
}

Messung V0.5
C=100 H=86 G=93

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge