Skip to content

Commit

Permalink
SELinux: add boundary support and thread context assignment
Browse files Browse the repository at this point in the history
The purpose of this patch is to assign per-thread security context
under a constraint. It enables multi-threaded server application
to kick a request handler with its fair security context, and
helps some of userspace object managers to handle user's request.

When we assign a per-thread security context, it must not have wider
permissions than the original one. Because a multi-threaded process
shares a single local memory, an arbitary per-thread security context
also means another thread can easily refer violated information.

The constraint on a per-thread security context requires a new domain
has to be equal or weaker than its original one, when it tries to assign
a per-thread security context.

Bounds relationship between two types is a way to ensure a domain can
never have wider permission than its bounds. We can define it in two
explicit or implicit ways.

The first way is using new TYPEBOUNDS statement. It enables to define
a boundary of types explicitly. The other one expand the concept of
existing named based hierarchy. If we defines a type with "." separated
name like "httpd_t.php", toolchain implicitly set its bounds on "httpd_t".

This feature requires a new policy version.
The 24th version (POLICYDB_VERSION_BOUNDARY) enables to ship them into
kernel space, and the following patch enables to handle it.

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Acked-by:  Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
  • Loading branch information
KaiGai Kohei authored and James Morris committed Aug 28, 2008
1 parent da31894 commit d9250de
Show file tree
Hide file tree
Showing 7 changed files with 398 additions and 20 deletions.
2 changes: 1 addition & 1 deletion security/selinux/avc.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
* @tclass: target security class
* @av: access vector
*/
static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{
const char **common_pts = NULL;
u32 common_base = 0;
Expand Down
15 changes: 12 additions & 3 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -5226,20 +5226,29 @@ static int selinux_setprocattr(struct task_struct *p,

if (sid == 0)
return -EINVAL;

/* Only allow single threaded processes to change context */
/*
* SELinux allows to change context in the following case only.
* - Single threaded processes.
* - Multi threaded processes intend to change its context into
* more restricted domain (defined by TYPEBOUNDS statement).
*/
if (atomic_read(&p->mm->mm_users) != 1) {
struct task_struct *g, *t;
struct mm_struct *mm = p->mm;
read_lock(&tasklist_lock);
do_each_thread(g, t) {
if (t->mm == mm && t != p) {
read_unlock(&tasklist_lock);
return -EPERM;
error = security_bounded_transition(tsec->sid, sid);
if (!error)
goto boundary_ok;

return error;
}
} while_each_thread(g, t);
read_unlock(&tasklist_lock);
}
boundary_ok:

/* Check permissions for the transition. */
error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Expand Down
4 changes: 4 additions & 0 deletions security/selinux/include/avc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/kdev_t.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/audit.h>
#include <linux/in6.h>
#include <linux/path.h>
#include <asm/system.h>
Expand Down Expand Up @@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms);

/* Shows permission in human readable form */
void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);

/* Exported to selinuxfs */
int avc_get_hash_stats(char *page);
extern unsigned int avc_cache_threshold;
Expand Down
15 changes: 14 additions & 1 deletion security/selinux/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
#define POLICYDB_VERSION_RANGETRANS 21
#define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
#define POLICYDB_VERSION_BOUNDARY 24

/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
#endif

#define CONTEXT_MNT 0x01
Expand Down Expand Up @@ -62,6 +63,16 @@ enum {
extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;

/*
* type_datum properties
* available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
*/
#define TYPEDATUM_PROPERTY_PRIMARY 0x0001
#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002

/* limitation of boundary depth */
#define POLICYDB_BOUNDS_MAXDEPTH 4

int security_load_policy(void *data, size_t len);

int security_policycap_supported(unsigned int req_cap);
Expand Down Expand Up @@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass);

int security_bounded_transition(u32 oldsid, u32 newsid);

int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);

int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
Expand Down
Loading

0 comments on commit d9250de

Please sign in to comment.