mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Kyle Moffett <kyle@moffetthome.net>
To: Casey Schaufler <casey@schaufler-ca.com>
Cc: "Michael Stone" <michael@laptop.org>,
	"Serge E. Hallyn" <serue@us.ibm.com>,
	linux-kernel@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	"Andi Kleen" <andi@firstfloor.org>, "David Lang" <david@lang.hm>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>,
	"Alan Cox" <alan@lxorguk.ukuu.org.uk>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"Valdis Kletnieks" <Valdis.Kletnieks@vt.edu>,
	"Bryan Donlan" <bdonlan@gmail.com>,
	"Evgeniy Polyakov" <zbr@ioremap.net>,
	"C. Scott Ananian" <cscott@cscott.net>,
	"James Morris" <jmorris@namei.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	"Bernie Innocenti" <bernie@codewiz.org>,
	"Mark Seaborn" <mrs@mythic-beasts.com>,
	"Randy Dunlap" <randy.dunlap@oracle.com>,
	"Américo Wang" <xiyou.wangcong@gmail.com>,
	"Tetsuo Handa" <penguin-kernel@i-love.sakura.ne.jp>,
	"Samir Bellabes" <sam@synack.fr>, "Pavel Machek" <pavel@ucw.cz>
Subject: Re: A basic question about the security_* hooks
Date: Tue, 29 Dec 2009 14:02:43 -0500	[thread overview]
Message-ID: <f73f7ab80912291102i22fb9e10v3b1b0eaba2e4f61d@mail.gmail.com> (raw)
In-Reply-To: <4B395EB8.4050902@schaufler-ca.com>

[-- Attachment #1: Type: text/plain, Size: 2398 bytes --]

On Mon, Dec 28, 2009 at 20:43, Casey Schaufler <casey@schaufler-ca.com> wrote:
> Kyle Moffett wrote:
>> On Sat, Dec 26, 2009 at 14:50, Michael Stone <michael@laptop.org> wrote:
>>> I'm willing to entertain pretty much any implementation or interface request
>>> which meets that goal and which implements the desired semantics.
>>>
>>
>> If you aren't using SELinux at this time (and therefore have no
>> existing policy), then it's actually pretty straightforward
>> (relatively speaking) to set up for your particular goals.  On top of
>> that, once you actually get the system set up, it's very easy to
>> extend your sandbox security model to additional processes, actions,
>> etc.
>>
>> [...]
>
> I would be very surprised if the policy you've described actually
> covered all the bases. I would also be surprised if a functional
> policy that meets the needs described was considerably smaller than
> Lake Michigan. It's really easy to toss off the basics of what needs
> to be done, it's quite another to get the whole thing right.
>
>> If all you need is something much simpler, the policy
>> language is very flexible and easy to customize.
>>
>
> I'm willing to bet all the beers you can drink in a sitting that
> the policy would be bigger than the proposed LSM. You can count that
> in either bytes or lines.

If that bet's in Mountain Dew or "Bawls" energy drinks
(http://www.bawls.com/) instead of beer... then you've got a deal :-D

Here's a very fast first cut at such a policy.  In this version I
actually completely ignore the type-enforcement mechanism, although if
you decide to start mediating file access then you may want to
reenable it.  The policy is pretty straightforward and easy to read...
customizations would initially mostly be in the "constraint" rules.

The only thing I actually had to write was the base-policy.pp file.  I
personally absolutely detest M4... so these particular files are
designed to be preprocessed with "cpp" instead.  Those 3 ".h" files
are simply lists of the kernel's access vectors and such run through
"sed" to convert the "#" comments into "//" comments.

I have a Makefile I've been using personally to build that policy, but
right now it's rather interdependent with my working environment, so
it may take me several days to find the time to extract it cleanly.

Cheers,
Kyle Moffett

[-- Attachment #2: access_vectors.h --]
[-- Type: application/octet-stream, Size: 8806 bytes --]

//
// Define common prefixes for access vectors
//
// common common_name { permission_name ... }


//
// Define a common prefix for file access vectors.
//

common file
{
	ioctl
	read
	write
	create
	getattr
	setattr
	lock
	relabelfrom
	relabelto
	append
	unlink
	link
	rename
	execute
	swapon
	quotaon
	mounton
}


//
// Define a common prefix for socket access vectors.
//

common socket
{
// inherited from file
	ioctl
	read
	write
	create
	getattr
	setattr
	lock
	relabelfrom
	relabelto
	append
// socket-specific
	bind
	connect
	listen
	accept
	getopt
	setopt
	shutdown
	recvfrom
	sendto
	recv_msg
	send_msg
	name_bind
}	

//
// Define a common prefix for ipc access vectors.
//

common ipc
{
	create
	destroy
	getattr
	setattr
	read
	write
	associate
	unix_read
	unix_write
}

//
//  Define a common prefix for userspace database object access vectors.
//

common database
{
	create
	drop
	getattr
	setattr
	relabelfrom
	relabelto
}

//
// Define a common prefix for pointer and keyboard access vectors.
//

common x_device
{
	getattr
	setattr
	use
	read
	write
	getfocus
	setfocus
	bell
	force_cursor
	freeze
	grab
	manage
	list_property
	get_property
	set_property
	add
	remove
	create
	destroy
}

//
// Define the access vectors.
//
// class class_name [ inherits common_name ] { permission_name ... }


//
// Define the access vector interpretation for file-related objects.
//

class filesystem
{
	mount
	remount
	unmount
	getattr
	relabelfrom
	relabelto
	transition
	associate
	quotamod
	quotaget
}

class dir
inherits file
{
	add_name
	remove_name
	reparent
	search
	rmdir
	open
}

class file
inherits file
{
	execute_no_trans
	entrypoint
	execmod
	open
}

class lnk_file
inherits file

class chr_file
inherits file
{
	execute_no_trans
	entrypoint
	execmod
	open
}

class blk_file
inherits file
{
	open
}

class sock_file
inherits file
{
	open
}

class fifo_file
inherits file
{
	open
}

class fd
{
	use
}


//
// Define the access vector interpretation for network-related objects.
//

class socket
inherits socket

class tcp_socket
inherits socket
{
	connectto
	newconn
	acceptfrom
	node_bind
	name_connect
}

class udp_socket
inherits socket
{
	node_bind
}

class rawip_socket
inherits socket
{
	node_bind
}

class node 
{
	tcp_recv
	tcp_send
	udp_recv
	udp_send
	rawip_recv
	rawip_send
	enforce_dest
	dccp_recv
	dccp_send
	recvfrom
	sendto
}

class netif
{
	tcp_recv
	tcp_send
	udp_recv
	udp_send
	rawip_recv
	rawip_send
	dccp_recv
	dccp_send
	ingress
	egress
}

class netlink_socket
inherits socket

class packet_socket
inherits socket

class key_socket
inherits socket

class unix_stream_socket
inherits socket
{
	connectto
	newconn
	acceptfrom
}

class unix_dgram_socket
inherits socket

//
// Define the access vector interpretation for process-related objects
//

class process
{
	fork
	transition
	sigchld // commonly granted from child to parent
	sigkill // cannot be caught or ignored
	sigstop // cannot be caught or ignored
	signull // for kill(pid, 0)
	signal  // all other signals
	ptrace
	getsched
	setsched
	getsession
	getpgid
	setpgid
	getcap
	setcap
	share
	getattr
	setexec
	setfscreate
	noatsecure
	siginh
	setrlimit
	rlimitinh
	dyntransition
	setcurrent
	execmem
	execstack
	execheap
	setkeycreate
	setsockcreate
}


//
// Define the access vector interpretation for ipc-related objects
//

class ipc
inherits ipc

class sem
inherits ipc

class msgq
inherits ipc
{
	enqueue
}

class msg
{
	send
	receive
}

class shm
inherits ipc
{
	lock
}


//
// Define the access vector interpretation for the security server. 
//

class security
{
	compute_av
	compute_create
	compute_member
	check_context
	load_policy
	compute_relabel
	compute_user
	setenforce     // was avc_toggle in system class
	setbool
	setsecparam
	setcheckreqprot
}


//
// Define the access vector interpretation for system operations.
//

class system
{
	ipc_info
	syslog_read  
	syslog_mod
	syslog_console
	module_request
}

//
// Define the access vector interpretation for controling capabilies
//

class capability
{
	// The capabilities are defined in include/linux/capability.h
	// Capabilities >= 32 are defined in the capability2 class.
	// Care should be taken to ensure that these are consistent with
	// those definitions. (Order matters)

	chown           
	dac_override    
	dac_read_search 
	fowner          
	fsetid          
	kill            
	setgid           
	setuid           
	setpcap          
	linux_immutable  
	net_bind_service 
	net_broadcast    
	net_admin        
	net_raw          
	ipc_lock         
	ipc_owner        
	sys_module       
	sys_rawio        
	sys_chroot       
	sys_ptrace       
	sys_pacct        
	sys_admin        
	sys_boot         
	sys_nice         
	sys_resource     
	sys_time         
	sys_tty_config  
	mknod
	lease
	audit_write
	audit_control
	setfcap
}

class capability2 
{
	mac_override	// unused by SELinux
	mac_admin	// unused by SELinux
}

//
// Define the access vector interpretation for controlling
// changes to passwd information.
//
class passwd
{
	passwd	// change another user passwd
	chfn	// change another user finger info
	chsh	// change another user shell
	rootok  // pam_rootok check (skip auth)
	crontab // crontab on another user
}

//
// SE-X Windows stuff
//
class x_drawable
{
	create
	destroy
	read
	write
	blend
	getattr
	setattr
	list_child
	add_child
	remove_child
	list_property
	get_property
	set_property
	manage
	override
	show
	hide
	send
	receive
}

class x_screen
{
	getattr
	setattr
	hide_cursor
	show_cursor
	saver_getattr
	saver_setattr
	saver_hide
	saver_show
}

class x_gc
{
	create
	destroy
	getattr
	setattr
	use
}

class x_font
{
	create
	destroy
	getattr
	add_glyph
	remove_glyph
	use
}

class x_colormap
{
	create
	destroy
	read
	write
	getattr
	add_color
	remove_color
	install
	uninstall
	use
}

class x_property
{
	create
	destroy
	read
	write
	append
	getattr
	setattr
}

class x_selection
{
	read
	write
	getattr
	setattr
}

class x_cursor
{
	create
	destroy
	read
	write
	getattr
	setattr
	use
}

class x_client
{
	destroy
	getattr
	setattr
	manage
}

class x_device
inherits x_device

class x_server
{
	getattr
	setattr
	record
	debug
	grab
	manage
}

class x_extension
{
	query
	use
}

class x_resource
{
	read
	write
}

class x_event
{
	send
	receive
}

class x_synthetic_event
{
	send
	receive
}

//
// Extended Netlink classes
//
class netlink_route_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
}

class netlink_firewall_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
}

class netlink_tcpdiag_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
}

class netlink_nflog_socket
inherits socket

class netlink_xfrm_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
}

class netlink_selinux_socket
inherits socket

class netlink_audit_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
	nlmsg_relay
	nlmsg_readpriv
	nlmsg_tty_audit
}

class netlink_ip6fw_socket
inherits socket
{
	nlmsg_read
	nlmsg_write
}

class netlink_dnrt_socket
inherits socket

// Define the access vector interpretation for controlling
// access and communication through the D-BUS messaging
// system.
//
class dbus
{
	acquire_svc
	send_msg
}

// Define the access vector interpretation for controlling
// access through the name service cache daemon (nscd).
//
class nscd
{
	getpwd
	getgrp
	gethost
	getstat
	admin
	shmempwd
	shmemgrp
	shmemhost
	getserv
	shmemserv
}

// Define the access vector interpretation for controlling
// access to IPSec network data by association
//
class association
{
	sendto
	recvfrom
	setcontext
	polmatch
}

// Updated Netlink class for KOBJECT_UEVENT family.
class netlink_kobject_uevent_socket
inherits socket

class appletalk_socket
inherits socket

class packet
{
	send
	recv
	relabelto
	flow_in		// deprecated
	flow_out	// deprecated
	forward_in
	forward_out
}

class key
{
	view
	read
	write
	search
	link
	setattr
	create
}

class context
{
	translate
	contains
}

class dccp_socket
inherits socket
{
	node_bind
	name_connect
}

class memprotect
{
	mmap_zero
}

class db_database
inherits database
{
	access
	install_module
	load_module
	get_param	// deprecated
	set_param	// deprecated
}

class db_table
inherits database
{
	use		// deprecated
	select
	update
	insert
	delete
	lock
}

class db_procedure
inherits database
{
	execute
	entrypoint
	install
}

class db_column
inherits database
{
	use		// deprecated
	select
	update
	insert
}

class db_tuple
{
	relabelfrom
	relabelto
	use		// deprecated
	select
	update
	insert
	delete
}

class db_blob
inherits database
{
	read
	write
	import
	export
}

// network peer labels
class peer
{
	recv
}

class x_application_data
{
	paste
	paste_after_confirm
	copy
}

class kernel_service
{
	use_as_override
	create_files_as	
}

class tun_socket
inherits socket

class x_pointer
inherits x_device

class x_keyboard
inherits x_device

[-- Attachment #3: base-policy.te --]
[-- Type: application/octet-stream, Size: 2332 bytes --]

/* These lists of binary access vectors match what the kernel expects */
#include <flask/security_classes.h>
#include <flask/initial_sids.h>
#include <flask/access_vectors.h>

/* Make sure we're running on a new enough kernel */
policycap network_peer_controls;

/* We have no attributes or booleans */

/* Only one type */
type any_t;

/* A few roles */
role obj_r;
role proc_r;
role nonet_r;

/* Allow each rule to assume the only type */
role obj_r   types any_t;
role proc_r  types any_t;
role nonet_r types any_t;

/* Completely disable type-enforcement */
allow any_t any_t:{ all_classes } *;

/* Only one "user" */
user any_u roles { obj_r proc_r nonet_r };

/* The below rules control what is or isn't allowed */

/* Make sure that "nonet" mode is unescapable */
constrain process { transition dyntransition noatsecure siginh rlimitinh } (
	(r1 == r2) or
	(r1 == proc_r and r2 == nonet_r)
);

/* 
 * Disallow various actions from nonet.  There are probably more hooks
 * missing from this list (see the very exhaustive list in the include file
 * <flask/access_vectors.h>), but they are trivial to add and very
 * straightforward.
 */
constrain tcp_socket { bind connect        } (r1 != nonet_r);
constrain udp_socket { bind connect sendto } (r1 != nonet_r);

// Default SIDs (Tell the kernel to label almost anything the same)
sid netmsg		any_u:obj_r:any_t
sid port		any_u:obj_r:any_t
sid node		any_u:obj_r:any_t
sid netif		any_u:obj_r:any_t
sid devnull		any_u:obj_r:any_t
sid file		any_u:obj_r:any_t
sid fs			any_u:obj_r:any_t
sid sysctl		any_u:obj_r:any_t
sid unlabeled		any_u:obj_r:any_t
sid any_socket		any_u:obj_r:any_t
sid file_labels		any_u:obj_r:any_t
sid icmp_socket		any_u:obj_r:any_t
sid igmp_packet		any_u:obj_r:any_t
sid init		any_u:obj_r:any_t
sid kmod		any_u:obj_r:any_t
sid policy		any_u:obj_r:any_t
sid scmp_packet		any_u:obj_r:any_t
sid sysctl_modprobe	any_u:obj_r:any_t
sid sysctl_fs		any_u:obj_r:any_t
sid sysctl_kernel	any_u:obj_r:any_t
sid sysctl_net		any_u:obj_r:any_t
sid sysctl_net_unix	any_u:obj_r:any_t
sid sysctl_vm		any_u:obj_r:any_t
sid sysctl_dev		any_u:obj_r:any_t
sid tcp_socket		any_u:obj_r:any_t
sid security		any_u:obj_r:any_t

// This label is used when the kernel starts new processes
sid kernel  any_u:proc_r:any_t

// No manual FS labels, everything should just pick up default SIDs

[-- Attachment #4: initial_sids.h --]
[-- Type: application/octet-stream, Size: 422 bytes --]

// FLASK

//
// Define initial security identifiers 
//

sid kernel
sid security
sid unlabeled
sid fs
sid file
sid file_labels
sid init
sid any_socket
sid port
sid netif
sid netmsg
sid node
sid igmp_packet
sid icmp_socket
sid tcp_socket
sid sysctl_modprobe
sid sysctl
sid sysctl_fs
sid sysctl_kernel
sid sysctl_net
sid sysctl_net_unix
sid sysctl_vm
sid sysctl_dev
sid kmod
sid policy
sid scmp_packet
sid devnull

// FLASK

[-- Attachment #5: security_classes.h --]
[-- Type: application/octet-stream, Size: 3670 bytes --]

// FLASK

//
// Define the security object classes 
//

// Classes marked as userspace are classes
// for userspace object managers

class security
class process
class system
class capability

// file-related classes
class filesystem
class file
class dir
class fd
class lnk_file
class chr_file
class blk_file
class sock_file
class fifo_file

// network-related classes
class socket
class tcp_socket
class udp_socket
class rawip_socket
class node
class netif
class netlink_socket
class packet_socket
class key_socket
class unix_stream_socket
class unix_dgram_socket

// sysv-ipc-related classes
class sem
class msg
class msgq
class shm
class ipc

//
// userspace object manager classes
//

// passwd/chfn/chsh
class passwd			// userspace

// SE-X Windows stuff (more classes below)
class x_drawable		// userspace
class x_screen			// userspace
class x_gc			// userspace
class x_font			// userspace
class x_colormap		// userspace
class x_property		// userspace
class x_selection		// userspace
class x_cursor			// userspace
class x_client			// userspace
class x_device			// userspace
class x_server			// userspace
class x_extension		// userspace

// extended netlink sockets
class netlink_route_socket
class netlink_firewall_socket
class netlink_tcpdiag_socket
class netlink_nflog_socket
class netlink_xfrm_socket
class netlink_selinux_socket
class netlink_audit_socket
class netlink_ip6fw_socket
class netlink_dnrt_socket

class dbus			// userspace
class nscd			// userspace

// IPSec association
class association

// Updated Netlink class for KOBJECT_UEVENT family.
class netlink_kobject_uevent_socket

class appletalk_socket

class packet

// Kernel access key retention
class key

class context			// userspace

class dccp_socket

class memprotect

class db_database		// userspace
class db_table			// userspace
class db_procedure		// userspace
class db_column			// userspace
class db_tuple			// userspace
class db_blob			// userspace

// network peer labels
class peer

// Capabilities >= 32
class capability2

// More SE-X Windows stuff
class x_resource		// userspace
class x_event			// userspace
class x_synthetic_event		// userspace
class x_application_data	// userspace

// kernel services that need to override task security, e.g. cachefiles
class kernel_service 

class tun_socket

// Still More SE-X Windows stuff
class x_pointer			// userspace
class x_keyboard		// userspace

#define all_classes			\
	security			\
	process				\
	system				\
	capability			\
	filesystem			\
	file				\
	dir				\
	fd				\
	lnk_file			\
	chr_file			\
	blk_file			\
	sock_file			\
	fifo_file			\
	socket				\
	tcp_socket			\
	udp_socket			\
	rawip_socket			\
	node				\
	netif				\
	netlink_socket			\
	packet_socket			\
	key_socket			\
	unix_stream_socket		\
	unix_dgram_socket		\
	sem				\
	msg				\
	msgq				\
	shm				\
	ipc				\
	passwd				\
	x_drawable			\
	x_screen			\
	x_gc				\
	x_font				\
	x_colormap			\
	x_property			\
	x_selection			\
	x_cursor			\
	x_client			\
	x_device			\
	x_server			\
	x_extension			\
	netlink_route_socket		\
	netlink_firewall_socket		\
	netlink_tcpdiag_socket		\
	netlink_nflog_socket		\
	netlink_xfrm_socket		\
	netlink_selinux_socket		\
	netlink_audit_socket		\
	netlink_ip6fw_socket		\
	netlink_dnrt_socket		\
	dbus				\
	nscd				\
	association			\
	netlink_kobject_uevent_socket	\
	appletalk_socket		\
	packet				\
	key				\
	context				\
	dccp_socket			\
	memprotect			\
	db_database			\
	db_table			\
	db_procedure			\
	db_column			\
	db_tuple			\
	db_blob				\
	peer				\
	capability2			\
	x_resource			\
	x_event				\
	x_synthetic_event		\
	x_application_data		\
	kernel_service			\
	tun_socket			\
	x_pointer			\
	x_keyboard

// FLASK

  reply	other threads:[~2009-12-29 19:03 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-24  2:29 Michael Stone
2009-12-24  4:50 ` Casey Schaufler
2009-12-24 12:53   ` Eric W. Biederman
2009-12-24 21:55     ` Tetsuo Handa
2009-12-25  0:05     ` Serge E. Hallyn
2009-12-31 17:50       ` David P. Quigley
2010-01-04  2:12     ` Paul Moore
2009-12-24  7:36 ` Evgeniy Polyakov
2009-12-24 18:57   ` Samir Bellabes
2009-12-25  0:14 ` Serge E. Hallyn
2009-12-25  1:11   ` Michael Stone
2009-12-25  5:50     ` Serge E. Hallyn
2009-12-26 19:50       ` Michael Stone
2009-12-27  3:16         ` Serge E. Hallyn
2009-12-27  4:02           ` Tetsuo Handa
2009-12-27 10:56             ` Valdis.Kletnieks
2009-12-27 14:54               ` Serge E. Hallyn
2009-12-27 20:28               ` David Wagner
2009-12-28  2:08                 ` Valdis.Kletnieks
2009-12-28 11:51               ` Tetsuo Handa
2009-12-28 14:45                 ` Valdis.Kletnieks
2009-12-28 14:51                 ` Valdis.Kletnieks
2009-12-29 13:01                   ` Label based MAC + Name based MAC (was Re: A basic question about the security_* hooks) Tetsuo Handa
2010-01-02 13:56                 ` A basic question about the security_* hooks Pavel Machek
2009-12-28 15:24         ` Kyle Moffett
2009-12-29  1:43           ` Casey Schaufler
2009-12-29 19:02             ` Kyle Moffett [this message]
2009-12-30 19:49               ` Casey Schaufler
2009-12-27  0:33       ` Mimi Zohar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f73f7ab80912291102i22fb9e10v3b1b0eaba2e4f61d@mail.gmail.com \
    --to=kyle@moffetthome.net \
    --cc=Valdis.Kletnieks@vt.edu \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=andi@firstfloor.org \
    --cc=bdonlan@gmail.com \
    --cc=bernie@codewiz.org \
    --cc=casey@schaufler-ca.com \
    --cc=cscott@cscott.net \
    --cc=david@lang.hm \
    --cc=ebiederm@xmission.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=jmorris@namei.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=michael@laptop.org \
    --cc=mrs@mythic-beasts.com \
    --cc=pavel@ucw.cz \
    --cc=penguin-kernel@i-love.sakura.ne.jp \
    --cc=randy.dunlap@oracle.com \
    --cc=sam@synack.fr \
    --cc=serue@us.ibm.com \
    --cc=socketcan@hartkopp.net \
    --cc=xiyou.wangcong@gmail.com \
    --cc=zbr@ioremap.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®