Skip to content

Commit

Permalink
SELinux: Use dentry name in new object labeling
Browse files Browse the repository at this point in the history
Currently SELinux has rules which label new objects according to 3 criteria.
The label of the process creating the object, the label of the parent
directory, and the type of object (reg, dir, char, block, etc.)  This patch
adds a 4th criteria, the dentry name, thus we can distinguish between
creating a file in an etc_t directory called shadow and one called motd.

There is no file globbing, regex parsing, or anything mystical.  Either the
policy exactly (strcmp) matches the dentry name of the object or it doesn't.
This patch has no changes from today if policy does not implement the new
rules.

Signed-off-by: Eric Paris <eparis@redhat.com>
  • Loading branch information
Eric Paris committed Feb 1, 2011
1 parent 2a7dba3 commit 652bb9b
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 37 deletions.
15 changes: 7 additions & 8 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -1301,10 +1301,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent

/* Try to obtain a transition SID. */
isec->sclass = inode_mode_to_security_class(inode->i_mode);
rc = security_transition_sid(isec->task_sid,
sbsec->sid,
isec->sclass,
&sid);
rc = security_transition_sid(isec->task_sid, sbsec->sid,
isec->sclass, NULL, &sid);
if (rc)
goto out_unlock;
isec->sid = sid;
Expand Down Expand Up @@ -1579,7 +1577,7 @@ static int may_create(struct inode *dir,
return rc;

if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);
if (rc)
return rc;
}
Expand Down Expand Up @@ -2061,7 +2059,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
} else {
/* Check for a default transition on this program. */
rc = security_transition_sid(old_tsec->sid, isec->sid,
SECCLASS_PROCESS, &new_tsec->sid);
SECCLASS_PROCESS, NULL,
&new_tsec->sid);
if (rc)
return rc;
}
Expand Down Expand Up @@ -2532,7 +2531,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
rc = security_transition_sid(sid, dsec->sid,
inode_mode_to_security_class(inode->i_mode),
&newsid);
qstr, &newsid);
if (rc) {
printk(KERN_WARNING "%s: "
"security_transition_sid failed, rc=%d (dev=%s "
Expand Down Expand Up @@ -4845,7 +4844,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
* message queue this message will be stored in
*/
rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
&msec->sid);
NULL, &msec->sid);
if (rc)
return rc;
}
Expand Down
8 changes: 5 additions & 3 deletions security/selinux/include/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#ifndef _SELINUX_SECURITY_H_
#define _SELINUX_SECURITY_H_

#include <linux/dcache.h>
#include <linux/magic.h>
#include <linux/types.h>
#include "flask.h"
Expand All @@ -28,13 +29,14 @@
#define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25

/* 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_BOUNDARY
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_FILENAME_TRANS
#endif

/* Mask for just the mount related flags */
Expand Down Expand Up @@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid,
void security_compute_av_user(u32 ssid, u32 tsid,
u16 tclass, struct av_decision *avd);

int security_transition_sid(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid);
int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
const struct qstr *qstr, u32 *out_sid);

int security_transition_sid_user(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid);
Expand Down
22 changes: 11 additions & 11 deletions security/selinux/ss/avtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* Copyright (C) 2003 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
Expand All @@ -27,16 +27,16 @@ struct avtab_key {
u16 source_type; /* source type */
u16 target_type; /* target type */
u16 target_class; /* target object class */
#define AVTAB_ALLOWED 1
#define AVTAB_AUDITALLOW 2
#define AVTAB_AUDITDENY 4
#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
#define AVTAB_TRANSITION 16
#define AVTAB_MEMBER 32
#define AVTAB_CHANGE 64
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
#define AVTAB_ALLOWED 0x0001
#define AVTAB_AUDITALLOW 0x0002
#define AVTAB_AUDITDENY 0x0004
#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
#define AVTAB_TRANSITION 0x0010
#define AVTAB_MEMBER 0x0020
#define AVTAB_CHANGE 0x0040
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
u16 specified; /* what field is specified */
};

Expand Down
130 changes: 130 additions & 0 deletions security/selinux/ss/policydb.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = {
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
{
.version = POLICYDB_VERSION_FILENAME_TRANS,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
};

static struct policydb_compat_info *policydb_lookup_compat(int version)
Expand Down Expand Up @@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p)
int i;
struct role_allow *ra, *lra = NULL;
struct role_trans *tr, *ltr = NULL;
struct filename_trans *ft, *nft;

for (i = 0; i < SYM_NUM; i++) {
cond_resched();
Expand Down Expand Up @@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p)
}
flex_array_free(p->type_attr_map_array);
}

ft = p->filename_trans;
while (ft) {
nft = ft->next;
kfree(ft->name);
kfree(ft);
ft = nft;
}

ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map);

Expand Down Expand Up @@ -1788,6 +1803,76 @@ static int range_read(struct policydb *p, void *fp)
return rc;
}

static int filename_trans_read(struct policydb *p, void *fp)
{
struct filename_trans *ft, *last;
u32 nel, len;
char *name;
__le32 buf[4];
int rc, i;

if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
return 0;

rc = next_entry(buf, fp, sizeof(u32));
if (rc)
goto out;
nel = le32_to_cpu(buf[0]);

printk(KERN_ERR "%s: nel=%d\n", __func__, nel);

last = p->filename_trans;
while (last && last->next)
last = last->next;

for (i = 0; i < nel; i++) {
rc = -ENOMEM;
ft = kzalloc(sizeof(*ft), GFP_KERNEL);
if (!ft)
goto out;

/* add it to the tail of the list */
if (!last)
p->filename_trans = ft;
else
last->next = ft;
last = ft;

/* length of the path component string */
rc = next_entry(buf, fp, sizeof(u32));
if (rc)
goto out;
len = le32_to_cpu(buf[0]);

rc = -ENOMEM;
name = kmalloc(len + 1, GFP_KERNEL);
if (!name)
goto out;

ft->name = name;

/* path component string */
rc = next_entry(name, fp, len);
if (rc)
goto out;
name[len] = 0;

printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name);

rc = next_entry(buf, fp, sizeof(u32) * 4);
if (rc)
goto out;

ft->stype = le32_to_cpu(buf[0]);
ft->ttype = le32_to_cpu(buf[1]);
ft->tclass = le32_to_cpu(buf[2]);
ft->otype = le32_to_cpu(buf[3]);
}
rc = 0;
out:
return rc;
}

static int genfs_read(struct policydb *p, void *fp)
{
int i, j, rc;
Expand Down Expand Up @@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp)
lra = ra;
}

rc = filename_trans_read(p, fp);
if (rc)
goto bad;

rc = policydb_index(p);
if (rc)
goto bad;
Expand Down Expand Up @@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp)
return 0;
}

static int filename_trans_write(struct policydb *p, void *fp)
{
struct filename_trans *ft;
u32 len, nel = 0;
__le32 buf[4];
int rc;

for (ft = p->filename_trans; ft; ft = ft->next)
nel++;

buf[0] = cpu_to_le32(nel);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

for (ft = p->filename_trans; ft; ft = ft->next) {
len = strlen(ft->name);
buf[0] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc)
return rc;

rc = put_entry(ft->name, sizeof(char), len, fp);
if (rc)
return rc;

buf[0] = ft->stype;
buf[1] = ft->ttype;
buf[2] = ft->tclass;
buf[3] = ft->otype;

rc = put_entry(buf, sizeof(u32), 4, fp);
if (rc)
return rc;
}
return 0;
}
/*
* Write the configuration data in a policy database
* structure to a policy database binary representation
Expand Down Expand Up @@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp)
if (rc)
return rc;

rc = filename_trans_write(p, fp);
if (rc)
return rc;

rc = ocontext_write(p, info, fp);
if (rc)
return rc;
Expand Down
14 changes: 13 additions & 1 deletion security/selinux/ss/policydb.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ struct role_trans {
struct role_trans *next;
};

struct filename_trans {
struct filename_trans *next;
u32 stype; /* current process */
u32 ttype; /* parent dir context */
u16 tclass; /* class of new object */
const char *name; /* last path component */
u32 otype; /* expected of new object */
};

struct role_allow {
u32 role; /* current role */
u32 new_role; /* new role */
Expand Down Expand Up @@ -217,6 +226,9 @@ struct policydb {
/* role transitions */
struct role_trans *role_tr;

/* file transitions with the last path component */
struct filename_trans *filename_trans;

/* bools indexed by (value - 1) */
struct cond_bool_datum **bool_val_to_struct;
/* type enforcement conditional access vectors and transitions */
Expand Down Expand Up @@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
return 0;
}

static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp)
static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp)
{
size_t len = bytes * num;

Expand Down
Loading

0 comments on commit 652bb9b

Please sign in to comment.