Grsecurity/How to Contribute
The easiest way to contribute is to enhance existing content by correcting misspelled words or restructuring sentences or paragraphs to make them more readable. You are also very welcome to add new content by expanding pages that are under development or by adding completely new pages if your text doesn't fit any of the other pages. As grsecurity is being actively developed and features are added and removed, help with keeping the content up to date is much appreciated.
On this page you will find background on why a particular structure was chosen for the book, who this book is for, and what style and formatting should be used.
Book Structure
[edit | edit source]The book's structure follows the original documentation of the grsecurity project that had three main chapters: Installation, Configuration and Specification, and Using gradm and the Learning Mode. Configuration and Specification was retitled as Policy Configuration. Using gradm and the Learning Mode was retitled as Administration and was also moved before the Policy Configuration, because you must know how to manage grsecurity before you configure the policy. This is how we ended up with the core structure: Installation, Administration, Policy Configuration.
Target Audience
[edit | edit source]The book is meant for people who are capable of solving hardware and software problems of varying complexity on their own and who actually read the manual. They know their way around their favorite Linux distribution and are familiar with configuring and building software from source.
Objectives
[edit | edit source]The purpose of this book is to provide comprehensive, reliable, and up-to-date documentation of grsecurity and related tools. In addition to teaching how to do something, the book provides information about best practices and common pitfalls learned in practice. This is the main objective.
Each chapter has additional objectives that define what the reader should know after they've read it. These objectives were defined after most of the book's core content was in place, so at the time of writing some chapters might not fulfill all of their objectives.
Introduction - The reader must learn on a basic level what grsecurity is, what are its goals and how those goals are realized. If they do not belong to our target audience they should still get a rough idea of what grsecurity is about.
Installation - The reader must learn:
- Where to get grsecurity, its administration tool gradm and the Linux kernel source.
- How to verify the authenticity of each package.
- How to apply the grsecurity patch properly.
- How to configure grsecurity's kernel configuration options (this includes PaX settings) and what they need to consider before doing so.
- How to build and install a grsecurity-enabled kernel using their chosen distribution's tools.
Administration - The reader must learn:
- How to install gradm, the administration tool.
- How to use gradm and especially the learning mode.
- How to configure grsecurity's features at runtime.
- What other useful tools are available, where to get them, and how to install and use them.
- How to troubleshoot application incompatibilities and problems with grsecurity.
Policy Configuration - The reader must learn:
- What an RBAC system is and is not, what it can provide when properly configured.
- What makes a secure policy.
- The policy structure and rules; they must be familiar with every configuration element and their parameters and configuration inheritance.
Reporting Bugs: The reader must learn how to report bugs; what information is required, how to gather it, and where to send the reports.
Style and Conventions
[edit | edit source]- Headers should be title cased.
- Use the <pre> tag to display long commands, example program output, and file contents.
- Use the XWarning template when you need to point out an important security consideration or a possibly dangerous operation. It is easier to spot than the classic Warning template when scrolling.
- Use the Info template when you need to point out something that's related to the surrounding text.
- The name grsecurity should be written in lowercase and without special formatting unless it begins a sentence. This is how it is written on the grsecurity website.
Formatting
[edit | edit source]Note: This is still a work in progress, and will change in the future. It will be finalized soon.
- Italic
- Used for file and directory names.
- Boldface
- Used for occasional emphasis, such as when introducing a new term.
- Constant Width
- Used in text for program and command names. Blocks of pre-formatted text is used in examples show what commands to execute and what their output should be.
Generating Content Automatically
[edit | edit source]Some content in this book can be generated automatically from grsecurity's source files. Scripts and programs that do this are listed here. Fixes and improvements to any of the scripts and programs are welcome, as are complete rewrites.
As this page and the scripts can be modified by anyone, take care to inspect all code before running it. |
Grsecurity and PaX Configuration Options and Sysctl Options
[edit | edit source]Below is a Python script that outputs two files, one with content for the Grsecurity and PaX Configuration Options page and another for the Sysctl Options page.
The script takes an absolute path to the kernel source patched with grsecurity as input, reads the grsecurity/grsec_sysctl.c, security/Kconfig, and grsecurity/Kconfig files, and outputs two files named Grsecurity_and_PaX_Configuration_Options.wiki and Sysctl_Options.wiki. The contents of Grsecurity_and_PaX_Configuration_Options.wiki can copied as they are to the wiki. Sysctl_Options.wiki only contains categorized lists of links that can be shown in the table on the Sysctl Options page. The links in the Sysctl_Options.wiki file point to anchors on the Grsecurity and PaX Configuration Options page, so the contents of these two files are linked.
The script uses Kconfiglib by Ulf Magnusson for reading the Kconfig files.
Feel free to replace the script with a Perl one-liner or a single command line.
#!/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")