mbox series

[v5,00/12] S.A.R.A. a new stacked LSM

Message ID 1562410493-8661-1-git-send-email-s.mesoraca16@gmail.com (mailing list archive)
Headers show
Series S.A.R.A. a new stacked LSM | expand

Message

Salvatore Mesoraca July 6, 2019, 10:54 a.m. UTC
S.A.R.A. (S.A.R.A. is Another Recursive Acronym) is a stacked Linux
Security Module that aims to collect heterogeneous security measures,
providing a common interface to manage them.
It can be useful to allow minor security features to use advanced
management options, like user-space configuration files and tools, without
too much overhead.
Some submodules that use this framework are also introduced.
The code is quite long, I apologize for this. Thank you in advance to
anyone who will take the time to review this patchset.

S.A.R.A. is meant to be stacked but it needs cred blobs and the procattr
interface, so I temporarily implemented those parts in a way that won't
be acceptable for upstream, but it works for now. I know that there
is some ongoing work to make cred blobs and procattr stackable, as soon
as the new interfaces will be available I'll reimplement the involved
parts.
At the moment I've been able to test it only on x86.

The only submodule introduced in this patchset is WX Protection.

The kernel-space part is complemented by its user-space counterpart:
saractl [1].
A test suite for WX Protection, called sara-test [2], is also available.

WX Protection aims to improve user-space programs security by applying:
- W^X enforcement: program can't have a page of memory that is marked, at
                   the same time, writable and executable.
- W!->X restriction: any page that could have been marked as writable in
                     the past won't ever be allowed to be marked as
                     executable.
- Executable MMAP prevention: prevents the creation of new executable mmaps
                              after the dynamic libraries have been loaded.
All of the above features can be enabled or disabled both system wide
or on a per executable basis through the use of configuration files managed
by "saractl".
It is important to note that some programs may have issues working with
WX Protection. In particular:
- W^X enforcement will cause problems to any programs that needs
  memory pages mapped both as writable and executable at the same time e.g.
  programs with executable stack markings in the PT_GNU_STACK segment.
- W!->X restriction will cause problems to any program that
  needs to generate executable code at run time or to modify executable
  pages e.g. programs with a JIT compiler built-in or linked against a
  non-PIC library.
- Executable MMAP prevention can work only with programs that have at least
  partial RELRO support. It's disabled automatically for programs that
  lack this feature. It will cause problems to any program that uses dlopen
  or tries to do an executable mmap. Unfortunately this feature is the one
  that could create most problems and should be enabled only after careful
  evaluation.
To extend the scope of the above features, despite the issues that they may
cause, they are complemented by:
- procattr interface: can be used by a program to discover which WX
                      Protection features are enabled and/or to tighten
                      them.
- Trampoline emulation: emulates the execution of well-known "trampolines"
                        even when they are placed in non-executable memory.
Parts of WX Protection are inspired by some of the features available in
PaX.

Thanks to the addition of extended attributes support, it's now possible to
use S.A.R.A. without being forced to rely on any special userspace tool.

More information can be found in the documentation introduced in the first
patch and in the "commit message" of the following emails.

Changes in v2:
        - Removed USB filtering submodule and relative hook
        - s/saralib/libsara/ typo
        - STR macro renamed to avoid conflicts
        - check_vmflags hook now returns an error code instead of just 1
          or 0. (suggested by Casey Schaufler)
        - pr_wxp macro rewritten as function for readability
        - Fixed i386 compilation warnings
        - Documentation now states clearly that changes done via procattr
          interface only apply to current thread. (suggested by Jann Horn)

Changes in v3:
        - Documentation has been moved to match the new directory structure.
        - Kernel cmdline arguments are now accessed via module_param interface
          (suggested by Kees Cook).
        - Created "sara_warn_or_return" macro to make WX Protection code more
          readable (suggested by Kees Cook).
        - Added more comments, in the most important places, to clarify my
          intentions (suggested by Kees Cook).
        - The "pagefault_handler" hook has been rewritten in a more "arch
          agnostic" way. Though it only support x86 at the moment
          (suggested by Kees Cook).

Changes in v4:
        - Documentation improved and some mistakes have been fixed.
        - Reduced dmesg verbosity.
        - check_vmflags is now also used to decide whether to ignore 
          GNU executable stack markings or not.
        - Added the check_vmflags hook in setup_arg_pages too.
        - Added support for extended attributes.
        - Moved trampoline emulation to arch/x86/ (suggested by Kees Cook).
        - SARA_WXP_MMAP now depends on SARA_WXP_OTHER.
        - MAC_ADMIN capability is now required also for config read.
        - Some other minor fixes not worth mentionig here.

Changes in v5:
        - Updated the code to use the new stacking interface.
        - Path matching is now done using a DFA

Salvatore Mesoraca (12):
  S.A.R.A.: add documentation
  S.A.R.A.: create framework
  S.A.R.A.: cred blob management
  S.A.R.A.: generic DFA for string matching
  LSM: creation of "check_vmflags" LSM hook
  S.A.R.A.: WX protection
  LSM: creation of "pagefault_handler" LSM hook
  S.A.R.A.: trampoline emulation
  S.A.R.A.: WX protection procattr interface
  S.A.R.A.: XATTRs support
  S.A.R.A.: /proc/*/mem write limitation
  MAINTAINERS: take maintainership for S.A.R.A.

 Documentation/admin-guide/LSM/SARA.rst          | 197 +++++
 Documentation/admin-guide/LSM/index.rst         |   1 +
 Documentation/admin-guide/kernel-parameters.txt |  40 +
 MAINTAINERS                                     |   9 +
 arch/Kconfig                                    |   6 +
 arch/x86/Kbuild                                 |   2 +
 arch/x86/Kconfig                                |   1 +
 arch/x86/mm/fault.c                             |   6 +
 arch/x86/security/Makefile                      |   2 +
 arch/x86/security/sara/Makefile                 |   1 +
 arch/x86/security/sara/emutramp.c               |  57 ++
 arch/x86/security/sara/trampolines32.h          | 137 ++++
 arch/x86/security/sara/trampolines64.h          | 164 ++++
 fs/binfmt_elf.c                                 |   3 +-
 fs/binfmt_elf_fdpic.c                           |   3 +-
 fs/exec.c                                       |   4 +
 fs/proc/base.c                                  |  11 +
 include/linux/lsm_hooks.h                       |  19 +
 include/linux/security.h                        |  17 +
 include/uapi/linux/xattr.h                      |   4 +
 mm/mmap.c                                       |  13 +
 security/Kconfig                                |  11 +-
 security/Makefile                               |   2 +
 security/sara/Kconfig                           | 176 +++++
 security/sara/Makefile                          |   5 +
 security/sara/dfa.c                             | 335 ++++++++
 security/sara/dfa_test.c                        | 135 ++++
 security/sara/include/dfa.h                     |  52 ++
 security/sara/include/dfa_test.h                |  29 +
 security/sara/include/emutramp.h                |  35 +
 security/sara/include/sara.h                    |  29 +
 security/sara/include/sara_data.h               | 100 +++
 security/sara/include/securityfs.h              |  61 ++
 security/sara/include/utils.h                   |  80 ++
 security/sara/include/wxprot.h                  |  29 +
 security/sara/main.c                            | 134 ++++
 security/sara/sara_data.c                       |  77 ++
 security/sara/securityfs.c                      | 565 ++++++++++++++
 security/sara/utils.c                           |  92 +++
 security/sara/wxprot.c                          | 998 ++++++++++++++++++++++++
 security/security.c                             |  16 +
 41 files changed, 3651 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/admin-guide/LSM/SARA.rst
 create mode 100644 arch/x86/security/Makefile
 create mode 100644 arch/x86/security/sara/Makefile
 create mode 100644 arch/x86/security/sara/emutramp.c
 create mode 100644 arch/x86/security/sara/trampolines32.h
 create mode 100644 arch/x86/security/sara/trampolines64.h
 create mode 100644 security/sara/Kconfig
 create mode 100644 security/sara/Makefile
 create mode 100644 security/sara/dfa.c
 create mode 100644 security/sara/dfa_test.c
 create mode 100644 security/sara/include/dfa.h
 create mode 100644 security/sara/include/dfa_test.h
 create mode 100644 security/sara/include/emutramp.h
 create mode 100644 security/sara/include/sara.h
 create mode 100644 security/sara/include/sara_data.h
 create mode 100644 security/sara/include/securityfs.h
 create mode 100644 security/sara/include/utils.h
 create mode 100644 security/sara/include/wxprot.h
 create mode 100644 security/sara/main.c
 create mode 100644 security/sara/sara_data.c
 create mode 100644 security/sara/securityfs.c
 create mode 100644 security/sara/utils.c
 create mode 100644 security/sara/wxprot.c

Comments

Jordan Glover July 6, 2019, 2:33 p.m. UTC | #1
On Saturday, July 6, 2019 10:54 AM, Salvatore Mesoraca <s.mesoraca16@gmail.com> wrote:

> S.A.R.A. is meant to be stacked but it needs cred blobs and the procattr
> interface, so I temporarily implemented those parts in a way that won't
> be acceptable for upstream, but it works for now. I know that there
> is some ongoing work to make cred blobs and procattr stackable, as soon
> as the new interfaces will be available I'll reimplement the involved
> parts.

I thought all stacking pieces for minor LSM were merged in Linux 5.1.
Is there still something missing or is this comment out-fo-date?

Jordan
Salvatore Mesoraca July 6, 2019, 3:02 p.m. UTC | #2
You are right. I just forgot to remove that paragraph from the cover letter.
My bad.
Thank you for noticing that :)

Il giorno sab 6 lug 2019 alle ore 16:33 Jordan Glover
<Golden_Miller83@protonmail.ch> ha scritto:
>
> On Saturday, July 6, 2019 10:54 AM, Salvatore Mesoraca <s.mesoraca16@gmail.com> wrote:
>
> > S.A.R.A. is meant to be stacked but it needs cred blobs and the procattr
> > interface, so I temporarily implemented those parts in a way that won't
> > be acceptable for upstream, but it works for now. I know that there
> > is some ongoing work to make cred blobs and procattr stackable, as soon
> > as the new interfaces will be available I'll reimplement the involved
> > parts.
>
> I thought all stacking pieces for minor LSM were merged in Linux 5.1.
> Is there still something missing or is this comment out-fo-date?
>
> Jordan
Randy Dunlap July 6, 2019, 3:38 p.m. UTC | #3
On 7/6/19 3:54 AM, Salvatore Mesoraca wrote:
> diff --git a/security/sara/Kconfig b/security/sara/Kconfig
> index b98cf27..54a96e0 100644
> --- a/security/sara/Kconfig
> +++ b/security/sara/Kconfig
> @@ -60,3 +60,77 @@ config SECURITY_SARA_NO_RUNTIME_ENABLE
>  
>  	  If unsure, answer Y.
>  
> +config SECURITY_SARA_WXPROT
> +	bool "WX Protection: W^X and W!->X protections"
> +	depends on SECURITY_SARA
> +	default y
> +	help
> +	  WX Protection aims to improve user-space programs security by applying:
> +	    - W^X memory restriction
> +	    - W!->X (once writable never executable) mprotect restriction
> +	    - Executable MMAP prevention
> +	  See Documentation/admin-guide/LSM/SARA.rst. for further information.

	                                        .rst for further information.

> +
> +	  If unsure, answer Y.
> +
> +choice
> +	prompt "Default action for W^X and W!->X protections"
> +	depends on SECURITY_SARA
> +	depends on SECURITY_SARA_WXPROT
> +	default SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_COMPLAIN_VERBOSE
> +
> +        help

Use tab instead of spaces for indentation above.

> +	  Choose the default behaviour of WX Protection when no config
> +	  rule matches or no rule is loaded.
> +	  For further information on available flags and their meaning
> +	  see Documentation/admin-guide/LSM/SARA.rst.
> +
> +	config SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_COMPLAIN_VERBOSE
> +		bool "Protections enabled but not enforced."
> +		help
> +		  All features enabled except "Executable MMAP prevention",
> +		  verbose reporting, but no actual enforce: it just complains.
> +		  Its numeric value is 0x3f, for more information see
> +		  Documentation/admin-guide/LSM/SARA.rst.
> +
> +        config SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_ENFORCE_VERBOSE
> +		bool "Full protection, verbose."
> +		help
> +		  All features enabled except "Executable MMAP prevention".
> +		  The enabled features will be enforced with verbose reporting.
> +		  Its numeric value is 0x2f, for more information see
> +		  Documentation/admin-guide/LSM/SARA.rst.
> +
> +        config SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_ENFORCE
> +		bool "Full protection, quiet."
> +		help
> +		  All features enabled except "Executable MMAP prevention".
> +		  The enabled features will be enforced quietly.
> +		  Its numeric value is 0xf, for more information see
> +		  Documentation/admin-guide/LSM/SARA.rst.
> +
> +	config SECURITY_SARA_WXPROT_DEFAULT_FLAGS_NONE
> +		bool "No protection at all."
> +		help
> +		  All features disabled.
> +		  Its numeric value is 0, for more information see
> +		  Documentation/admin-guide/LSM/SARA.rst.
> +endchoice
> +
> +config SECURITY_SARA_WXPROT_DISABLED
> +	bool "WX protection will be disabled at boot."
> +	depends on SECURITY_SARA_WXPROT
> +	default n

Omit "default n" please.

> +	help
> +	  If you say Y here WX protection won't be enabled at startup. You can
> +	  override this option via user-space utilities or at boot time via
> +	  "sara.wxprot_enabled=[0|1]" kernel parameter.
> +
> +	  If unsure, answer N.
> +
> +config SECURITY_SARA_WXPROT_DEFAULT_FLAGS
> +	hex
> +	default "0x3f" if SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_COMPLAIN_VERBOSE
> +	default "0x2f" if SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_ENFORCE_VERBOSE
> +	default "0xf" if SECURITY_SARA_WXPROT_DEFAULT_FLAGS_ALL_ENFORCE
> +	default "0" if SECURITY_SARA_WXPROT_DEFAULT_FLAGS_NONE
James Morris July 7, 2019, 1:16 a.m. UTC | #4
On Sat, 6 Jul 2019, Salvatore Mesoraca wrote:

> S.A.R.A. (S.A.R.A. is Another Recursive Acronym) is a stacked Linux

Please make this just SARA. Nobody wants to read or type S.A.R.A.
Salvatore Mesoraca July 7, 2019, 3:40 p.m. UTC | #5
James Morris <jmorris@namei.org> wrote:
>
> On Sat, 6 Jul 2019, Salvatore Mesoraca wrote:
>
> > S.A.R.A. (S.A.R.A. is Another Recursive Acronym) is a stacked Linux
>
> Please make this just SARA. Nobody wants to read or type S.A.R.A.

Agreed.
Thank you for your suggestion.
Salvatore Mesoraca July 7, 2019, 3:49 p.m. UTC | #6
Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> On Sat, Jul 06, 2019 at 12:54:47PM +0200, Salvatore Mesoraca wrote:
>
> > +#define sara_warn_or_return(err, msg) do {           \
> > +     if ((sara_wxp_flags & SARA_WXP_VERBOSE))        \
> > +             pr_wxp(msg);                            \
> > +     if (!(sara_wxp_flags & SARA_WXP_COMPLAIN))      \
> > +             return -err;                            \
> > +} while (0)
> > +
> > +#define sara_warn_or_goto(label, msg) do {           \
> > +     if ((sara_wxp_flags & SARA_WXP_VERBOSE))        \
> > +             pr_wxp(msg);                            \
> > +     if (!(sara_wxp_flags & SARA_WXP_COMPLAIN))      \
> > +             goto label;                             \
> > +} while (0)
>
> No.  This kind of "style" has no place in the kernel.
>
> Don't hide control flow.  It's nasty enough to reviewers,
> but it's pure hell on anyone who strays into your code while
> chasing a bug or doing general code audit.  In effect, you
> are creating your oh-so-private C dialect and assuming that
> everyone who ever looks at your code will start with learning
> that *AND* incorporating it into their mental C parser.
> I'm sorry, but you are not that important.
>
> If it looks like a function call, a casual reader will assume
> that this is exactly what it is.  And when one is scanning
> through a function (e.g. to tell if handling of some kind
> of refcounts is correct, with twentieth grep through the
> tree having brought something in your code into the view),
> the last thing one wants is to switch between the area-specific
> C dialects.  Simply because looking at yours is sandwiched
> between digging through some crap in drivers/target/ and that
> weird thing in kernel/tracing/, hopefully staying limited
> to 20 seconds of glancing through several functions in your
> code.
>
> Don't Do That.  Really.

I understand your concerns.
The first version of SARA didn't use these macros,
they were added because I was asked[1] to do so.

I have absolutely no problems in reverting this change.
I just want to make sure that there is agreement on this matter.
Maybe Kees can clarify his stance.

Thank you for your suggestions.

[1] https://lkml.kernel.org/r/CAGXu5jJuQx2qOt_aDqDQDcqGOZ5kmr5rQ9Zjv=MRRCJ65ERfGw@mail.gmail.com
David Laight July 8, 2019, 12:42 p.m. UTC | #7
From: Salvatore Mesoraca
> Sent: 06 July 2019 11:55
...
> Executable MMAP prevention works by preventing any new executable
> allocation after the dynamic libraries have been loaded. It works under the
> assumption that, when the dynamic libraries have been finished loading, the
> RELRO section will be marked read only.

What about writing to the file of a dynamic library after it is loaded
but before it is faulted it (or after evicting it from the I$).

...
> +#define find_relro_section(ELFH, ELFP, FILE, RELRO, FOUND) do {		\
> +	unsigned long i;						\
> +	int _tmp;							\
> +	loff_t _pos = 0;						\
> +	if (ELFH.e_type == ET_DYN || ELFH.e_type == ET_EXEC) {		\
> +		for (i = 0; i < ELFH.e_phnum; ++i) {			\
> +			_pos = ELFH.e_phoff + i*sizeof(ELFP);		\
> +			_tmp = kernel_read(FILE, &ELFP, sizeof(ELFP),	\
> +					   &_pos);			\
> +			if (_tmp != sizeof(ELFP))			\
> +				break;					\
> +			if (ELFP.p_type == PT_GNU_RELRO) {		\
> +				RELRO = ELFP.p_offset >> PAGE_SHIFT;	\
> +				FOUND = true;				\
> +				break;					\
> +			}						\
> +		}							\
> +	}								\
> +} while (0)

This is big for a #define.
Since it contains kernel_read() it can't really matter if it is
a real function.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)