Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/arch/powerpc/kernel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  secvar-sysfs.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2019 IBM Corporation <nayna@linux.ibm.com>
 *
 * This code exposes secure variables to user via sysfs
 */


#define pr_fmt(fmt) "secvar-sysfs: "fmt

#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/string.h>
#include <linux/of.h>
#include <asm/secvar.h>

#define NAME_MAX_SIZE    1024

static struct kobject *secvar_kobj;
static struct kset *secvar_kset;

static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
      char *buf)
{
 char tmp[32];
 ssize_t len = secvar_ops->format(tmp, sizeof(tmp));

 if (len > 0)
  return sysfs_emit(buf, "%s\n", tmp);
 else if (len < 0)
  pr_err("Error %zd reading format string\n", len);
 else
  pr_err("Got empty format string from backend\n");

 return -EIO;
}


static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
    char *buf)
{
 u64 dsize;
 int rc;

 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
 if (rc) {
  if (rc != -ENOENT)
   pr_err("Error retrieving %s variable size %d\n", kobj->name, rc);
  return rc;
 }

 return sysfs_emit(buf, "%llu\n", dsize);
}

static ssize_t data_read(struct file *filep, struct kobject *kobj,
    const struct bin_attribute *attr, char *buf, loff_t off,
    size_t count)
{
 char *data;
 u64 dsize;
 int rc;

 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
 if (rc) {
  if (rc != -ENOENT)
   pr_err("Error getting %s variable size %d\n", kobj->name, rc);
  return rc;
 }
 pr_debug("dsize is %llu\n", dsize);

 data = kzalloc(dsize, GFP_KERNEL);
 if (!data)
  return -ENOMEM;

 rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, data, &dsize);
 if (rc) {
  pr_err("Error getting %s variable %d\n", kobj->name, rc);
  goto data_fail;
 }

 rc = memory_read_from_buffer(buf, count, &off, data, dsize);

data_fail:
 kfree(data);
 return rc;
}

static ssize_t update_write(struct file *filep, struct kobject *kobj,
       const struct bin_attribute *attr, char *buf, loff_t off,
       size_t count)
{
 int rc;

 pr_debug("count is %ld\n", count);
 rc = secvar_ops->set(kobj->name, strlen(kobj->name) + 1, buf, count);
 if (rc) {
  pr_err("Error setting the %s variable %d\n", kobj->name, rc);
  return rc;
 }

 return count;
}

static struct kobj_attribute format_attr = __ATTR_RO(format);

static struct kobj_attribute size_attr = __ATTR_RO(size);

static struct bin_attribute data_attr __ro_after_init = __BIN_ATTR_RO(data, 0);

static struct bin_attribute update_attr __ro_after_init = __BIN_ATTR_WO(update, 0);

static const struct bin_attribute *const secvar_bin_attrs[] = {
 &data_attr,
 &update_attr,
 NULL,
};

static struct attribute *secvar_attrs[] = {
 &size_attr.attr,
 NULL,
};

static const struct attribute_group secvar_attr_group = {
 .attrs = secvar_attrs,
 .bin_attrs = secvar_bin_attrs,
};
__ATTRIBUTE_GROUPS(secvar_attr);

static const struct kobj_type secvar_ktype = {
 .sysfs_ops = &kobj_sysfs_ops,
 .default_groups = secvar_attr_groups,
};

static __init int update_kobj_size(void)
{

 u64 varsize;
 int rc = secvar_ops->max_size(&varsize);

 if (rc)
  return rc;

 data_attr.size = varsize;
 update_attr.size = varsize;

 return 0;
}

static __init int secvar_sysfs_config(struct kobject *kobj)
{
 struct attribute_group config_group = {
  .name = "config",
  .attrs = (struct attribute **)secvar_ops->config_attrs,
 };

 if (secvar_ops->config_attrs)
  return sysfs_create_group(kobj, &config_group);

 return 0;
}

static __init int add_var(const char *name)
{
 struct kobject *kobj;
 int rc;

 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
 if (!kobj)
  return -ENOMEM;

 kobject_init(kobj, &secvar_ktype);

 rc = kobject_add(kobj, &secvar_kset->kobj, "%s", name);
 if (rc) {
  pr_warn("kobject_add error %d for attribute: %s\n", rc,
   name);
  kobject_put(kobj);
  return rc;
 }

 kobject_uevent(kobj, KOBJ_ADD);
 return 0;
}

static __init int secvar_sysfs_load(void)
{
 u64 namesize = 0;
 char *name;
 int rc;

 name = kzalloc(NAME_MAX_SIZE, GFP_KERNEL);
 if (!name)
  return -ENOMEM;

 do {
  rc = secvar_ops->get_next(name, &namesize, NAME_MAX_SIZE);
  if (rc) {
   if (rc != -ENOENT)
    pr_err("error getting secvar from firmware %d\n", rc);
   else
    rc = 0;

   break;
  }

  rc = add_var(name);
 } while (!rc);

 kfree(name);
 return rc;
}

static __init int secvar_sysfs_load_static(void)
{
 const char * const *name_ptr = secvar_ops->var_names;
 int rc;

 while (*name_ptr) {
  rc = add_var(*name_ptr);
  if (rc)
   return rc;
  name_ptr++;
 }

 return 0;
}

static __init int secvar_sysfs_init(void)
{
 u64 max_size;
 int rc;

 if (!secvar_ops) {
  pr_warn("Failed to retrieve secvar operations\n");
  return -ENODEV;
 }

 secvar_kobj = kobject_create_and_add("secvar", firmware_kobj);
 if (!secvar_kobj) {
  pr_err("Failed to create firmware kobj\n");
  return -ENOMEM;
 }

 rc = sysfs_create_file(secvar_kobj, &format_attr.attr);
 if (rc) {
  pr_err("Failed to create format object\n");
  rc = -ENOMEM;
  goto err;
 }

 secvar_kset = kset_create_and_add("vars", NULL, secvar_kobj);
 if (!secvar_kset) {
  pr_err("sysfs kobject registration failed\n");
  rc = -ENOMEM;
  goto err;
 }

 rc = update_kobj_size();
 if (rc) {
  pr_err("Cannot read the size of the attribute\n");
  goto err;
 }

 rc = secvar_sysfs_config(secvar_kobj);
 if (rc) {
  pr_err("Failed to create config directory\n");
  goto err;
 }

 if (secvar_ops->get_next)
  rc = secvar_sysfs_load();
 else
  rc = secvar_sysfs_load_static();

 if (rc) {
  pr_err("Failed to create variable attributes\n");
  goto err;
 }

 // Due to sysfs limitations, we will only ever get a write buffer of
 // up to 1 page in size. Print a warning if this is potentially going
 // to cause problems, so that the user is aware.
 secvar_ops->max_size(&max_size);
 if (max_size > PAGE_SIZE)
  pr_warn_ratelimited("PAGE_SIZE (%lu) is smaller than maximum object size (%llu), writes are limited to PAGE_SIZE\n",
        PAGE_SIZE, max_size);

 return 0;
err:
 kobject_put(secvar_kobj);
 return rc;
}

late_initcall(secvar_sysfs_init);

Messung V0.5
C=99 H=87 G=93

¤ Dauer der Verarbeitung: 0.9 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.