跳至内容

Grsecurity/如何贡献

来自维基教科书,开放世界中的开放书籍
Grsecurity
术语 如何贡献 获取 grsecurity


最简单的贡献方式是通过纠正拼写错误或重构句子或段落以使其更易读来增强现有内容。您也欢迎添加新内容,方法是扩展正在开发中的页面,或者如果您添加的文本不适合其他任何页面,则添加全新的页面。由于 grsecurity 正在积极开发中,并且功能在不断添加和删除,因此非常感谢您帮助保持内容的最新状态。

在本页,您将找到有关为何为本书选择特定结构的背景信息、本书的受众以及应使用哪种风格和格式。

书籍结构

[编辑 | 编辑源代码]

本书的结构遵循 grsecurity 项目的原始文档,该文档包含三个主要章节:安装、配置和规范以及使用 gradm 和学习模式。配置和规范被重新命名为策略配置。使用 gradm 和学习模式被重新命名为管理,并且也被移到策略配置之前,因为您必须了解如何在配置策略之前管理 grsecurity。这就是我们最终得到核心结构的方式:安装、管理、策略配置。

目标受众

[编辑 | 编辑源代码]

本书面向能够独立解决不同复杂程度的硬件和软件问题,并且真正阅读手册的人。他们熟悉自己喜欢的 Linux 发行版,并且熟悉从源代码配置和构建软件。

本书旨在提供全面、可靠和最新的 grsecurity 及相关工具文档。除了教授如何做某事之外,本书还提供了有关实践中学习到的最佳实践和常见陷阱的信息。这是主要目标。

每个章节都有额外的目标,这些目标定义了读者在阅读完章节后应该了解的内容。这些目标是在本书大部分核心内容到位后定义的,因此在撰写本文时,某些章节可能无法满足所有目标。

简介 - 读者必须在基本层面上了解什么是 grsecurity,它的目标是什么以及这些目标是如何实现的。如果他们不属于我们的目标受众,他们仍然应该对 grsecurity 的基本内容有一个大致了解。

安装 - 读者必须了解

  • 从哪里获取 grsecurity、它的管理工具 gradm 以及 Linux 内核源代码。
  • 如何验证每个软件包的真实性。
  • 如何正确应用 grsecurity 补丁。
  • 如何配置 grsecurity 的内核配置选项(这包括 PaX 设置),以及在执行此操作之前需要考虑哪些因素。
  • 如何使用他们选择的发行版的工具构建和安装启用 grsecurity 的内核。

管理 - 读者必须了解

  • 如何安装管理工具 gradm。
  • 如何使用 gradm,尤其是学习模式。
  • 如何配置 grsecurity 的运行时功能。
  • 还提供了哪些其他有用工具,从哪里获取这些工具,以及如何安装和使用这些工具。
  • 如何解决应用程序兼容性问题和 grsecurity 问题。

策略配置 - 读者必须了解

  • 什么是 RBAC 系统以及它不是什么,在正确配置后它可以提供什么。
  • 什么构成了一个安全策略。
  • 策略结构和规则;他们必须熟悉每个配置元素及其参数和配置继承。

报告错误:读者必须了解如何报告错误;需要哪些信息,如何收集这些信息以及将报告发送到哪里。

风格和约定

[编辑 | 编辑源代码]
  • 标题应为标题大小写
  • 使用<pre> 标签显示长命令、示例程序输出和文件内容。
  • 当您需要指出重要的安全注意事项或可能危险的操作时,请使用XWarning 模板。滚动时,它比经典的Warning 模板更容易发现。
  • 当您需要指出与周围文本相关的内容时,请使用Info 模板
  • 名称 grsecurity 应写成小写,并且不使用特殊格式,除非它是一个句子的开头。这就是它在 grsecurity 网站上的写法。

注意:这仍然是一个正在进行的工作,将来会发生变化。它将很快完成。

斜体
用于文件和目录名称。
粗体
用于偶尔强调,例如在介绍新术语时。
等宽字体
在文本中用于程序和命令名称。预格式化文本块用于显示示例,显示要执行的命令以及它们的输出应该是什么。

自动生成内容

[编辑 | 编辑源代码]

本书中的一些内容可以从 grsecurity 的源文件中自动生成。执行此操作的脚本和程序列在此处。欢迎对任何脚本和程序的修复和改进,以及完整的重写。

Warning 由于此页面和脚本可以由任何人修改,因此在运行任何代码之前,请务必检查所有代码。

Grsecurity 和 PaX 配置选项Sysctl 选项

[编辑 | 编辑源代码]

下面是一个Python 脚本,它输出两个文件,一个用于Grsecurity 和 PaX 配置选项 页面,另一个用于Sysctl 选项 页面。

该脚本将修补了 grsecurity 的内核源代码的绝对路径作为输入,读取grsecurity/grsec_sysctl.csecurity/Kconfiggrsecurity/Kconfig 文件,并输出两个名为Grsecurity_and_PaX_Configuration_Options.wikiSysctl_Options.wiki 的文件。Grsecurity_and_PaX_Configuration_Options.wiki 的内容可以原样复制到维基百科。Sysctl_Options.wiki 仅包含可以显示在Sysctl 选项 页面上的表格中的链接分类列表。Sysctl_Options.wiki 文件中的链接指向Grsecurity 和 PaX 配置选项 页面上的锚点,因此这两个文件的内容是链接的。

该脚本使用 Ulf Magnusson 编写的Kconfiglib 来读取 Kconfig 文件。

您可以随意用 Perl 单行程序或单个命令行替换该脚本。

#!/usr/bin/env python

import sys
import codecs
import os
import kconfiglib

def get_sysctl_opts(kern_src_dir):
    """
    Returns a dictionary of sysctl variables related to grsecurity.

    Parameters:
    kern_src_dir    (string) Absolute path to a kernel source directory
                    (e.g. /usr/src/linux-3.2.48.)

    The key of each item is the name of a kernel configuration symbol (e.g.
    GRKERNSEC_SYMLINKOWN) and the value is a list of sysctl variable names
    (e.g. [enforce_symlinksifowner, symlinkown_gid]).
    """
    file_name = os.path.join(kern_src_dir, "grsecurity", "grsec_sysctl.c")
    options = {}
    with open(file_name, 'r') as f:
        cur_symbol = None
        for line in f:
            if line.startswith("#ifdef"):
                start = line.find("GRKERNSEC")
                cur_symbol = line[start:].strip()
                options[cur_symbol] = []
            elif line.startswith("#endif"):
                if cur_symbol in options:
                    options[cur_symbol].sort()
                cur_symbol = None

            if cur_symbol is not None and line.find(".procname") >= 0:
                a = line.find('"') + 1 
                b = line.rfind('"')
                sysctl_var = line[a:b].strip()
                options[cur_symbol].append(sysctl_var)

    return options


def get_categorized_sysctl_opts(sysctl_opts):
    """
    Returns a list of lists or tuples.

    Parameters:
    sysctl_opts     (dict) Dictionary of sysctl variables. This would be the
                    return value of get_sysctl_opts().

    Each index in the returned list specifies a category. The categories are
    [0] Audit/logging variables
    [1] Chroot variables
    [2] Network variables
    [3] Misc. variables

    The categorization is based on the name of the sysctl variable, and is
    not entirely accurate. But it's "good enough."

    Each category consists of a list of tuples. The first element of a tuple
    is the name of a kernel configuration symbol (e.g. GRKERNSEC_SYMLINKOWN)
    and the second element is a sysctl variable that is related to that
    symbol. If a symbol is related to more than one sysctl variable, the list
    will contain multiple tuples that have the same first element.
    """
    audit_opts = []
    chroot_opts = []
    net_opts = []
    other_opts = []

    for item in sysctl_opts.iteritems():
        for opt in item[1]:
            if opt.find("audit") >= 0 or opt.find("log") >= 0:
                audit_opts.append((opt,item[0]))
            elif opt.find("chroot") >= 0:
                chroot_opts.append((opt,item[0]))
            elif opt.find("socket") >= 0 or opt.find("ip") >= 0:
                net_opts.append((opt,item[0]))
            else:
                other_opts.append((opt,item[0]))

    audit_opts.sort()
    chroot_opts.sort()
    net_opts.sort()
    other_opts.sort()
    all_opts = [audit_opts, chroot_opts, net_opts, other_opts]

    return all_opts


def write_wikified_sysctl_opts(kern_src_dir, out_file_name):
    """
    Writes a categorized list of sysctl variables wrapped in MediaWiki links
    constructs.

    Parameters:
    kern_src_dir    (string) Absolute path to a kernel source directory
                    (e.g. /usr/src/linux-3.2.48.)

    out_file_name   (string) Path and file name or just the file name of the
                    output file.

    The links point to anchors on the Grsecurity and PaX Configuration Options
    page. The links are written in alphabetical order by the sysctl variable.
    """
    sysctl_opts = get_sysctl_opts(kern_src_dir)
    categorized_opts = get_categorized_sysctl_opts(sysctl_opts)
    kconfig_path = os.path.join(kern_src_dir, "security", "Kconfig")
    conf = kconfiglib.Config(kconfig_path, kern_src_dir)
    link_fmt = "* [[Grsecurity/Appendix/Grsecurity_and_PaX"\
        "_Configuration_Options#{0}|{1}]]\n"

    with codecs.open(out_file_name, 'w', "utf-8") as f:
        f.write("Category: Audit/logging\n")
        for opt in categorized_opts[0]:
            symbol = conf.get_symbol(opt[1])
            prompt = get_prompt(symbol)
            f.write(link_fmt.format(prompt, opt[0]))

        f.write("\nCategory: Chroot\n")
        for opt in categorized_opts[1]:
            symbol = conf.get_symbol(opt[1])
            prompt = get_prompt(symbol)
            f.write(link_fmt.format(prompt, opt[0]))

        f.write("\nCategory: Network\n")
        for opt in categorized_opts[2]:
            symbol = conf.get_symbol(opt[1])
            prompt = get_prompt(symbol)
            f.write(link_fmt.format(prompt, opt[0]))

        f.write("\nCategory: Miscellaneous\n")
        for opt in categorized_opts[3]:
            symbol = conf.get_symbol(opt[1])
            prompt = get_prompt(symbol)
            f.write(link_fmt.format(prompt, opt[0]))


def get_prompt(item):
    """ 
    Return the first prompt text of the specified symbol or choice.

    Parameters:
    item        (Kconfiglib.Symbol or Kconfiglib.Choice) The object whose
                prompt is to be returned.

    Kconfiglib does not expose the prompt(s) of a Symbol or Choice. They have
    to be extracted from the string representation of a Symbol object. This
    function only returns the first prompt. There may be more prompts and
    they may or may not be identical.
    """
    s = str(item)
    prefix = "Prompts:"
    i = s.find(prefix)
    prompt = None
    if i >= 0:
        a = s.find('"', i + len(prefix)) + 1
        b = s.find('"', a)
        prompt = s[a:b]

    return prompt


def write_wikified_item(f, sysctl_opts, item, level):
    """
    Write the given Kconfiglib.Item in the specified file.

    Parameters:
    f               (file) Output file object open for writing.

    sysctl_opts     (dict) Dictionary of sysctl variables. This would be the
                    return value of get_sysctl_opts().

    item            (Kconfiglib.Item) Item that should be formatted.

    level           (integer) Heading level (number of '=' characters before
                    and after a heading). Items are hierarchical and this
                    function will increment the level when it calls itself
                    recursively to process child Items.

    This function wraps certain properties of item and related content from
    sysctl_opts in MediaWiki markup and writes the output to the specified
    file object.

    If item is a Menu, it is formatted as a heading and its child Items
    are iterated and formatted.

    If item is a Choice, its prompt text is formatted as a heading and
    help text as preformatted text.

    If item is a Symbol, its prompt text is formatted as a heading, name as
    teletype text, help text as preformatted text and all related sysctl
    options as intended lines below a sort of heading that's regular
    unformatted text.
    """
    heading_fmt = "\n{0}{1}{0}\n"
    symbol_fmt = "<tt>{0}</tt><br/>\n"
    help_fmt = "<pre>{0}</pre>\n"
    sysctl_vars_heading = "Related sysctl variables:<br/>\n"
    sysctl_var_fmt = ":<tt>kernel.grsecurity.{0}</tt>\n"

    if item.is_menu():
        if level > 1:
            f.write(heading_fmt.format("=" * level, item.get_title()))
        for subitem in item.get_items():
            write_wikified_item(f, sysctl_opts, subitem, level + 1)

    if item.is_choice():
        f.write(heading_fmt.format("=" * level, get_prompt(item)))
        help_text = item.get_help()
        if help_text is not None and len(help_text) > 0:
            f.write(help_fmt.format(help_text.strip()))
        for subitem in item.get_items():
            write_wikified_item(f, sysctl_opts, subitem, level + 1)

    if item.is_symbol():
        name = item.get_name().strip()
        prompt = get_prompt(item)
        help_text = item.get_help()

        if prompt is not None and len(prompt) >= 3:
            f.write(heading_fmt.format("=" * level, prompt))
            f.write(symbol_fmt.format(name))

            if name in sysctl_opts:
                opt_list = sysctl_opts[name]
                if opt_list is not None and len(opt_list) > 0:
                    f.write(sysctl_vars_heading)
                    for opt in sysctl_opts[name]:
                        f.write(sysctl_var_fmt.format(opt))

            if help_text is not None and len(help_text) > 0:
                f.write(help_fmt.format(help_text.strip()))


def write_wikified_kconfig(kern_src_dir, out_file_name):
    """
    Create a MediaWiki-formatted version of the Kconfig file found in
    the kern_src_dir/security/ directory and write the output to the
    given file.

    Parameters:
    kern_src_dir    (string) Absolute path to a kernel source directory
                    (e.g. /usr/src/linux-3.2.48.)

    out_file_name   (string) Path and file name or just the file name of the
                    output file.
    """
    security_kconfig = os.path.join(kern_src_dir, "security", "Kconfig")
    conf = kconfiglib.Config(security_kconfig, kern_src_dir)
    if conf is not None:
        for menu in conf.get_menus():
            if menu.get_title() == "Grsecurity":
                with codecs.open(out_file_name, 'w', "utf-8") as f:
                    sysctl_opts = get_sysctl_opts(kern_src_dir)
                    write_wikified_item(f, sysctl_opts, menu, 1)
                break

# kern_src_dir is expected to be an absolute path to the kernel
# source directory (e.g. /usr/src/linux-3.2.48).
kern_src_dir = sys.argv[1]
if kern_src_dir is not None and len(kern_src_dir) > 0:
    write_wikified_kconfig(kern_src_dir,
        "Grsecurity_and_PaX_Configuration_Options.wiki")
    write_wikified_sysctl_opts(kern_src_dir, "Sysctl_Options.wiki")
下一页: 获取 grsecurity | 上一页: 术语
主页: Grsecurity
华夏公益教科书