* This patch adds a new subs_dist file.
@ 2011-04-06 21:08 Daniel J Walsh
2011-04-12 13:33 ` Steve Lawrence
2011-04-18 10:41 ` This patch adds a new subs_dist file Richard Haines
0 siblings, 2 replies; 8+ messages in thread
From: Daniel J Walsh @ 2011-04-06 21:08 UTC (permalink / raw)
To: SELinux
[-- Attachment #1: Type: text/plain, Size: 738 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
The idea is to allow distributions to ship a subs file as well as let
the user modify subs.
In F16 we are looking at shipping a
file_contexts.subs_dist file like this
cat file_contexts.subs_dist
/run /var/run
/run/lock /var/lock
/var/run/lock /var/lock
/lib64 /lib
/usr/lib64 /usr/lib
The we will remove all (64)? from policy.
This will allow us to make sure all /usr/lib/libBLAH is labeled the same
as /usr/lib64/libBLAH
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk2c1ksACgkQrlYvE4MpobNXcQCgqgAiQJxmwa1+NdIq8E3tQRp6
QT0An0ihA60di9CRsEqEdVbSaHOwtte5
=LXgd
-----END PGP SIGNATURE-----
[-- Attachment #2: libselinux-subs.patch --]
[-- Type: text/plain, Size: 3810 bytes --]
diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
index 0725b57..f110dcf 100644
--- a/libselinux/include/selinux/selinux.h
+++ b/libselinux/include/selinux/selinux.h
@@ -482,6 +482,7 @@ extern const char *selinux_file_context_path(void);
extern const char *selinux_file_context_homedir_path(void);
extern const char *selinux_file_context_local_path(void);
extern const char *selinux_file_context_subs_path(void);
+extern const char *selinux_file_context_subs_dist_path(void);
extern const char *selinux_homedir_context_path(void);
extern const char *selinux_media_context_path(void);
extern const char *selinux_virtual_domain_context_path(void);
diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h
index ccf43e1..0b00156 100644
--- a/libselinux/src/file_path_suffixes.h
+++ b/libselinux/src/file_path_suffixes.h
@@ -23,4 +23,5 @@ S_(BINPOLICY, "/policy/policy")
S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context")
S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context")
S_(FILE_CONTEXT_SUBS, "/contexts/files/file_contexts.subs")
+ S_(FILE_CONTEXT_SUBS_DIST, "/contexts/files/file_contexts.subs_dist")
S_(SEPGSQL_CONTEXTS, "/contexts/sepgsql_contexts")
diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index 2fd19c5..ba316df 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -56,12 +56,11 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src)
return NULL;
}
-static struct selabel_sub *selabel_subs_init(void)
+static struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
{
char buf[1024];
- FILE *cfg = fopen(selinux_file_context_subs_path(), "r");
+ FILE *cfg = fopen(path, "r");
struct selabel_sub *sub;
- struct selabel_sub *list = NULL;
if (cfg) {
while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) {
@@ -160,7 +159,10 @@ struct selabel_handle *selabel_open(unsigned int backend,
memset(rec, 0, sizeof(*rec));
rec->backend = backend;
rec->validating = selabel_is_validate_set(opts, nopts);
- rec->subs = selabel_subs_init();
+
+ rec->subs = NULL;
+ rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
+ rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
if ((*initfuncs[backend])(rec, opts, nopts)) {
free(rec);
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index e040959..f4c33df 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -45,7 +45,8 @@
#define VIRTUAL_IMAGE 22
#define FILE_CONTEXT_SUBS 23
#define SEPGSQL_CONTEXTS 24
-#define NEL 25
+#define FILE_CONTEXT_SUBS_DIST 25
+#define NEL 26
/* Part of one-time lazy init */
static pthread_once_t once = PTHREAD_ONCE_INIT;
@@ -423,6 +424,12 @@ const char * selinux_file_context_subs_path(void) {
hidden_def(selinux_file_context_subs_path)
+const char * selinux_file_context_subs_dist_path(void) {
+ return get_path(FILE_CONTEXT_SUBS_DIST);
+}
+
+hidden_def(selinux_file_context_subs_dist_path)
+
const char *selinux_sepgsql_context_path()
{
return get_path(SEPGSQL_CONTEXTS);
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index fdddfaf..806e87c 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -65,6 +66,7 @@ hidden_proto(selinux_mkload_policy)
hidden_proto(selinux_file_context_path)
hidden_proto(selinux_file_context_homedir_path)
hidden_proto(selinux_file_context_local_path)
+ hidden_proto(selinux_file_context_subs_dist_path)
hidden_proto(selinux_file_context_subs_path)
hidden_proto(selinux_netfilter_context_path)
hidden_proto(selinux_homedir_context_path)
[-- Attachment #3: libselinux-subs.patch.sig --]
[-- Type: application/pgp-signature, Size: 72 bytes --]
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: This patch adds a new subs_dist file.
2011-04-06 21:08 This patch adds a new subs_dist file Daniel J Walsh
@ 2011-04-12 13:33 ` Steve Lawrence
2011-04-12 16:12 ` Daniel J Walsh
2011-04-18 10:41 ` This patch adds a new subs_dist file Richard Haines
1 sibling, 1 reply; 8+ messages in thread
From: Steve Lawrence @ 2011-04-12 13:33 UTC (permalink / raw)
To: Daniel J Walsh; +Cc: SELinux
On 04/06/2011 05:08 PM, Daniel J Walsh wrote:
> The idea is to allow distributions to ship a subs file as well as let
> the user modify subs.
>
> In F16 we are looking at shipping a
>
> file_contexts.subs_dist file like this
>
> cat file_contexts.subs_dist
> /run /var/run
> /run/lock /var/lock
> /var/run/lock /var/lock
> /lib64 /lib
> /usr/lib64 /usr/lib
>
>
> The we will remove all (64)? from policy.
>
> This will allow us to make sure all /usr/lib/libBLAH is labeled the same
> as /usr/lib64/libBLAH
>
Applied in libselinux-2.0.102
Thanks!
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: This patch adds a new subs_dist file.
2011-04-12 13:33 ` Steve Lawrence
@ 2011-04-12 16:12 ` Daniel J Walsh
2011-04-12 18:35 ` Here is an updated Eric Paris patch for adding named file trans rules Daniel J Walsh
0 siblings, 1 reply; 8+ messages in thread
From: Daniel J Walsh @ 2011-04-12 16:12 UTC (permalink / raw)
To: Steve Lawrence; +Cc: SELinux
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Your current patch for libsepol is broken. It is missing Epasis File
Trans patch so you have holes in the numbering
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk2kegEACgkQrlYvE4MpobM5cwCghnkuLSBr4MkJB7whBJNCDEOl
3+oAoI6IBvOWmlb/tx5e0goKLy9lpcf6
=IrVR
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Here is an updated Eric Paris patch for adding named file trans rules.
2011-04-12 16:12 ` Daniel J Walsh
@ 2011-04-12 18:35 ` Daniel J Walsh
2011-04-12 19:20 ` Steve Lawrence
0 siblings, 1 reply; 8+ messages in thread
From: Daniel J Walsh @ 2011-04-12 18:35 UTC (permalink / raw)
To: Steve Lawrence; +Cc: SELinux, Eric Paris, Harry Ciao
[-- Attachment #1: Type: text/plain, Size: 440 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
It also has a fix for the ROLE_TRANS patch from Harry Ciao that was
blowing up when used with policy less then 26. IE Everywhere.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk2km4gACgkQrlYvE4MpobM86gCgiZiD4xYD7Y+lO9c0hJUF/Bbb
8jsAn3C2LEnem+EVeJ1C1MscImk2moRB
=wfjo
-----END PGP SIGNATURE-----
[-- Attachment #2: libsepol-rhat.patch --]
[-- Type: text/plain, Size: 19896 bytes --]
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 94b8609..eebf1a9 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -136,6 +136,16 @@ typedef struct role_allow {
struct role_allow *next;
} role_allow_t;
+/* filename_trans rules */
+typedef struct filename_trans {
+ uint32_t stype;
+ uint32_t ttype;
+ uint32_t tclass;
+ char *name;
+ uint32_t otype;
+ struct filename_trans *next;
+} filename_trans_t;
+
/* Type attributes */
typedef struct type_datum {
symtab_datum_t s;
@@ -247,6 +257,15 @@ typedef struct role_allow_rule {
struct role_allow_rule *next;
} role_allow_rule_t;
+typedef struct filename_trans_rule {
+ type_set_t stypes;
+ type_set_t ttypes;
+ uint32_t tclass;
+ char *name;
+ uint32_t otype; /* new type */
+ struct filename_trans_rule *next;
+} filename_trans_rule_t;
+
typedef struct range_trans_rule {
type_set_t stypes;
type_set_t ttypes;
@@ -376,6 +395,9 @@ typedef struct avrule_decl {
scope_index_t required; /* symbols needed to activate this block */
scope_index_t declared; /* symbols declared within this block */
+ /* type transition rules with a 'name' component */
+ filename_trans_rule_t *filename_trans_rules;
+
/* for additive statements (type attribute, roles, and users) */
symtab_t symtab[SYM_NUM];
@@ -486,6 +508,9 @@ typedef struct policydb {
/* role transitions */
role_trans_t *role_tr;
+ /* type transition rules with a 'name' component */
+ filename_trans_t *filename_trans;
+
/* role allows */
role_allow_t *role_allow;
@@ -564,6 +589,8 @@ extern void avrule_destroy(avrule_t * x);
extern void avrule_list_destroy(avrule_t * x);
extern void role_trans_rule_init(role_trans_rule_t * x);
extern void role_trans_rule_list_destroy(role_trans_rule_t * x);
+extern void filename_trans_rule_init(filename_trans_rule_t * x);
+extern void filename_trans_rule_list_destroy(filename_trans_rule_t * x);
extern void role_datum_init(role_datum_t * x);
extern void role_datum_destroy(role_datum_t * x);
@@ -632,6 +659,7 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
#define POLICYDB_VERSION_BOUNDARY 24
+#define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26
/* Range of policy versions we understand*/
@@ -648,6 +676,7 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define MOD_POLICYDB_VERSION_PERMISSIVE 8
#define MOD_POLICYDB_VERSION_BOUNDARY 9
#define MOD_POLICYDB_VERSION_BOUNDARY_ALIAS 10
+#define MOD_POLICYDB_VERSION_FILENAME_TRANS 11
#define MOD_POLICYDB_VERSION_ROLETRANS 12
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index 8d1f8f6..16c89f3 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -98,6 +98,7 @@ void avrule_decl_destroy(avrule_decl_t * x)
cond_list_destroy(x->cond_list);
avrule_list_destroy(x->avrules);
role_trans_rule_list_destroy(x->role_tr_rules);
+ filename_trans_rule_list_destroy(x->filename_trans_rules);
role_allow_rule_list_destroy(x->role_allow_rules);
range_trans_rule_list_destroy(x->range_tr_rules);
scope_index_destroy(&x->required);
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 8539f88..b1af365 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -1237,6 +1237,101 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
return 0;
}
+static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
+{
+ unsigned int i, j;
+ filename_trans_t *new_trans, *tail, *cur_trans;
+ filename_trans_rule_t *cur_rule;
+ ebitmap_t stypes, ttypes;
+ ebitmap_node_t *snode, *tnode;
+
+ /* start at the end of the list */
+ tail = state->out->filename_trans;
+ while (tail && tail->next)
+ tail = tail->next;
+
+ cur_rule = rules;
+ while (cur_rule) {
+ ebitmap_init(&stypes);
+ ebitmap_init(&ttypes);
+
+ if (expand_convert_type_set(state->out, state->typemap,
+ &cur_rule->stypes, &stypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ if (expand_convert_type_set(state->out, state->typemap,
+ &cur_rule->ttypes, &ttypes, 1)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+
+ ebitmap_for_each_bit(&stypes, snode, i) {
+ if (!ebitmap_node_get_bit(snode, i))
+ continue;
+ ebitmap_for_each_bit(&ttypes, tnode, j) {
+ if (!ebitmap_node_get_bit(tnode, j))
+ continue;
+
+ cur_trans = state->out->filename_trans;
+ while (cur_trans) {
+ if ((cur_trans->stype == i + 1) &&
+ (cur_trans->ttype == j + 1) &&
+ (cur_trans->tclass == cur_rule->tclass) &&
+ (!strcmp(cur_trans->name, cur_rule->name))) {
+ /* duplicate rule, who cares */
+ if (cur_trans->otype == cur_rule->otype)
+ break;
+
+ ERR(state->handle, "Conflicting filename trans rules %s %s %s : %s otype1:%s otype2:%s",
+ cur_trans->name,
+ state->out->p_type_val_to_name[i],
+ state->out->p_type_val_to_name[j],
+ state->out->p_class_val_to_name[cur_trans->tclass - 1],
+ state->out->p_type_val_to_name[cur_trans->otype - 1],
+ state->out->p_type_val_to_name[state->typemap[cur_rule->otype - 1] - 1]);
+
+ return -1;
+ }
+ cur_trans = cur_trans->next;
+ }
+ /* duplicate rule, who cares */
+ if (cur_trans)
+ continue;
+
+ new_trans = malloc(sizeof(*new_trans));
+ if (!new_trans) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ memset(new_trans, 0, sizeof(*new_trans));
+ if (tail)
+ tail->next = new_trans;
+ else
+ state->out->filename_trans = new_trans;
+ tail = new_trans;
+
+ new_trans->name = strdup(cur_rule->name);
+ if (!new_trans->name) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ new_trans->stype = i + 1;
+ new_trans->ttype = j + 1;
+ new_trans->tclass = cur_rule->tclass;
+ new_trans->otype = state->typemap[cur_rule->otype - 1];
+ }
+ }
+
+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&ttypes);
+
+ cur_rule = cur_rule->next;
+ }
+ return 0;
+}
+
static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass,
mls_semantic_range_t * trange,
expand_state_t * state)
@@ -2380,6 +2475,9 @@ static int copy_and_expand_avrule_block(expand_state_t * state)
goto cleanup;
}
+ if (expand_filename_trans(state, decl->filename_trans_rules))
+ goto cleanup;
+
/* expand the range transition rules */
if (expand_range_trans(state, decl->range_tr_rules))
goto cleanup;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index e33db0f..23dbb1b 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -1340,6 +1340,50 @@ static int copy_role_allow_list(role_allow_rule_t * list,
return -1;
}
+static int copy_filename_trans_list(filename_trans_rule_t * list,
+ filename_trans_rule_t ** dst,
+ policy_module_t * module,
+ link_state_t * state)
+{
+ filename_trans_rule_t *cur, *new_rule, *tail;
+
+ cur = list;
+ tail = *dst;
+ while (tail && tail->next)
+ tail = tail->next;
+
+ while (cur) {
+ new_rule = malloc(sizeof(*new_rule));
+ if (!new_rule)
+ goto err;
+
+ filename_trans_rule_init(new_rule);
+
+ if (*dst == NULL)
+ *dst = new_rule;
+ else
+ tail->next = new_rule;
+ tail = new_rule;
+
+ new_rule->name = strdup(cur->name);
+ if (!new_rule->name)
+ goto err;
+
+ if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module, state) ||
+ type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module, state))
+ goto err;
+
+ new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1];
+ new_rule->otype = module->map[SYM_TYPES][cur->otype - 1];
+
+ cur = cur->next;
+ }
+ return 0;
+err:
+ ERR(state->handle, "Out of memory!");
+ return -1;
+}
+
static int copy_range_trans_list(range_trans_rule_t * rules,
range_trans_rule_t ** dst,
policy_module_t * mod, link_state_t * state)
@@ -1582,6 +1626,11 @@ static int copy_avrule_decl(link_state_t * state, policy_module_t * module,
return -1;
}
+ if (copy_filename_trans_list(src_decl->filename_trans_rules,
+ &dest_decl->filename_trans_rules,
+ module, state))
+ return -1;
+
if (copy_range_trans_list(src_decl->range_tr_rules,
&dest_decl->range_tr_rules, module, state))
return -1;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index bbf3c88..096b556 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -143,6 +143,13 @@ static struct policydb_compat_info policydb_compat[] = {
.ocon_num = OCON_NODE6 + 1,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_FILENAME_TRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
{
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
@@ -200,6 +207,13 @@ static struct policydb_compat_info policydb_compat[] = {
.target_platform = SEPOL_TARGET_SELINUX,
},
{
+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_FILENAME_TRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NODE6 + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
+ {
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -255,6 +269,13 @@ static struct policydb_compat_info policydb_compat[] = {
.ocon_num = 0,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_FILENAME_TRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
};
#if 0
@@ -456,6 +477,33 @@ void role_trans_rule_list_destroy(role_trans_rule_t * x)
}
}
+void filename_trans_rule_init(filename_trans_rule_t * x)
+{
+ memset(x, 0, sizeof(*x));
+ type_set_init(&x->stypes);
+ type_set_init(&x->ttypes);
+}
+
+static void filename_trans_rule_destroy(filename_trans_rule_t * x)
+{
+ if (!x)
+ return;
+ type_set_destroy(&x->stypes);
+ type_set_destroy(&x->ttypes);
+ free(x->name);
+}
+
+void filename_trans_rule_list_destroy(filename_trans_rule_t * x)
+{
+ filename_trans_rule_t *next;
+ while (x) {
+ next = x->next;
+ filename_trans_rule_destroy(x);
+ free(x);
+ x = next;
+ }
+}
+
void role_allow_rule_init(role_allow_rule_t * x)
{
memset(x, 0, sizeof(role_allow_rule_t));
@@ -1135,6 +1183,7 @@ void policydb_destroy(policydb_t * p)
role_allow_t *ra, *lra = NULL;
role_trans_t *tr, *ltr = NULL;
range_trans_t *rt, *lrt = NULL;
+ filename_trans_t *ft, *nft;
if (!p)
return;
@@ -1200,6 +1249,14 @@ void policydb_destroy(policydb_t * p)
if (ltr)
free(ltr);
+ ft = p->filename_trans;
+ while (ft) {
+ nft = ft->next;
+ free(ft->name);
+ free(ft);
+ ft = nft;
+ }
+
for (ra = p->role_allow; ra; ra = ra->next) {
if (lra)
free(lra);
@@ -2201,6 +2258,55 @@ int role_allow_read(role_allow_t ** r, struct policy_file *fp)
return 0;
}
+int filename_trans_read(filename_trans_t **t, struct policy_file *fp)
+{
+ unsigned int i;
+ uint32_t buf[4], nel, len;
+ filename_trans_t *ft, *lft;
+ int rc;
+ char *name;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+
+ lft = NULL;
+ for (i = 0; i < nel; i++) {
+ ft = calloc(1, sizeof(struct filename_trans));
+ if (!ft)
+ return -1;
+ if (lft)
+ lft->next = ft;
+ else
+ *t = ft;
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ len = le32_to_cpu(buf[0]);
+
+ name = calloc(len, sizeof(*name));
+ if (!name)
+ return -1;
+
+ ft->name = name;
+
+ rc = next_entry(name, fp, len);
+ if (rc < 0)
+ return -1;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
+ if (rc < 0)
+ return -1;
+
+ 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]);
+ }
+ return 0;
+}
+
static int ocontext_read_xen(struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
@@ -2927,7 +3033,8 @@ int avrule_read_list(policydb_t * p, avrule_t ** avrules,
return 0;
}
-static int role_trans_rule_read(role_trans_rule_t ** r, struct policy_file *fp)
+static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r,
+ struct policy_file *fp)
{
uint32_t buf[1], nel;
unsigned int i;
@@ -2958,8 +3065,9 @@ static int role_trans_rule_read(role_trans_rule_t ** r, struct policy_file *fp)
if (type_set_read(&tr->types, fp))
return -1;
- if (ebitmap_read(&tr->classes, fp))
- return -1;
+ if (p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS)
+ if (ebitmap_read(&tr->classes, fp))
+ return -1;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
@@ -3007,6 +3115,62 @@ static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp)
return 0;
}
+static int filename_trans_rule_read(filename_trans_rule_t ** r, struct policy_file *fp)
+{
+ uint32_t buf[2], nel;
+ unsigned int i, len;
+ filename_trans_rule_t *ftr, *lftr;
+ int rc;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ lftr = NULL;
+ for (i = 0; i < nel; i++) {
+ ftr = malloc(sizeof(*ftr));
+ if (!ftr)
+ return -1;
+
+ filename_trans_rule_init(ftr);
+
+ if (lftr)
+ lftr->next = ftr;
+ else
+ *r = ftr;
+ lftr = ftr;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+
+ len = le32_to_cpu(buf[0]);
+
+ ftr->name = malloc(len + 1);
+ if (!ftr->name)
+ return -1;
+
+ rc = next_entry(ftr->name, fp, len);
+ if (rc)
+ return -1;
+ ftr->name[len] = 0;
+
+ if (type_set_read(&ftr->stypes, fp))
+ return -1;
+
+ if (type_set_read(&ftr->ttypes, fp))
+ return -1;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
+ if (rc < 0)
+ return -1;
+ ftr->tclass = le32_to_cpu(buf[0]);
+ ftr->otype = le32_to_cpu(buf[1]);
+ }
+
+ return 0;
+}
+
static int range_trans_rule_read(range_trans_rule_t ** r,
struct policy_file *fp)
{
@@ -3096,10 +3260,15 @@ static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl,
decl->enabled = le32_to_cpu(buf[1]);
if (cond_read_list(p, &decl->cond_list, fp) == -1 ||
avrule_read_list(p, &decl->avrules, fp) == -1 ||
- role_trans_rule_read(&decl->role_tr_rules, fp) == -1 ||
+ role_trans_rule_read(p, &decl->role_tr_rules, fp) == -1 ||
role_allow_rule_read(&decl->role_allow_rules, fp) == -1) {
return -1;
}
+
+ if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
+ filename_trans_rule_read(&decl->filename_trans_rules, fp))
+ return -1;
+
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
range_trans_rule_read(&decl->range_tr_rules, fp) == -1) {
return -1;
@@ -3491,6 +3660,9 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
goto bad;
if (role_allow_read(&p->role_allow, fp))
goto bad;
+ if (r_policyvers >= POLICYDB_VERSION_FILENAME_TRANS &&
+ filename_trans_read(&p->filename_trans, fp))
+ goto bad;
} else {
/* first read the AV rule blocks, then the scope tables */
avrule_block_destroy(p->global);
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index f9d59b6..9b70e3c 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -528,6 +528,42 @@ static int role_allow_write(role_allow_t * r, struct policy_file *fp)
return POLICYDB_SUCCESS;
}
+static int filename_trans_write(filename_trans_t * r, struct policy_file *fp)
+{
+ filename_trans_t *ft;
+ uint32_t buf[4];
+ size_t nel, items, len;
+
+ nel = 0;
+ for (ft = r; ft; ft = ft->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ for (ft = r; ft; ft = ft->next) {
+ len = strlen(ft->name);
+ buf[0] = cpu_to_le32(len);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+
+ items = put_entry(ft->name, sizeof(char), len, fp);
+ if (items != len)
+ return POLICYDB_ERROR;
+
+ buf[0] = cpu_to_le32(ft->stype);
+ buf[1] = cpu_to_le32(ft->ttype);
+ buf[2] = cpu_to_le32(ft->tclass);
+ buf[3] = cpu_to_le32(ft->otype);
+ items = put_entry(buf, sizeof(uint32_t), 4, fp);
+ if (items != 4)
+ return POLICYDB_ERROR;
+ }
+
+ return POLICYDB_SUCCESS;
+}
+
static int role_set_write(role_set_t * x, struct policy_file *fp)
{
size_t items;
@@ -1446,7 +1482,8 @@ static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
return POLICYDB_SUCCESS;
}
-static int role_trans_rule_write(role_trans_rule_t * t, struct policy_file *fp)
+static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
+ struct policy_file *fp)
{
int nel = 0;
size_t items;
@@ -1464,8 +1501,9 @@ static int role_trans_rule_write(role_trans_rule_t * t, struct policy_file *fp)
return POLICYDB_ERROR;
if (type_set_write(&tr->types, fp))
return POLICYDB_ERROR;
- if (ebitmap_write(&tr->classes, fp))
- return POLICYDB_ERROR;
+ if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS)
+ if (ebitmap_write(&tr->classes, fp))
+ return POLICYDB_ERROR;
buf[0] = cpu_to_le32(tr->new_role);
items = put_entry(buf, sizeof(uint32_t), 1, fp);
if (items != 1)
@@ -1496,6 +1534,47 @@ static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
return POLICYDB_SUCCESS;
}
+static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
+{
+ int nel = 0;
+ size_t items;
+ uint32_t buf[2], len;
+ filename_trans_rule_t *ftr;
+
+ for (ftr = t; ftr; ftr = ftr->next)
+ nel++;
+
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+
+ for (ftr = t; ftr; ftr = ftr->next) {
+ len = strlen(ftr->name);
+ buf[0] = cpu_to_le32(len);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+
+ items = put_entry(ftr->name, sizeof(char), len, fp);
+ if (items != len)
+ return POLICYDB_ERROR;
+
+ if (type_set_write(&ftr->stypes, fp))
+ return POLICYDB_ERROR;
+ if (type_set_write(&ftr->ttypes, fp))
+ return POLICYDB_ERROR;
+
+ buf[0] = cpu_to_le32(ftr->tclass);
+ buf[1] = cpu_to_le32(ftr->otype);
+
+ items = put_entry(buf, sizeof(uint32_t), 2, fp);
+ if (items != 2)
+ return POLICYDB_ERROR;
+ }
+ return POLICYDB_SUCCESS;
+}
+
static int range_trans_rule_write(range_trans_rule_t * t,
struct policy_file *fp)
{
@@ -1559,10 +1638,15 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
}
if (cond_write_list(p, decl->cond_list, fp) == -1 ||
avrule_write_list(decl->avrules, fp) == -1 ||
- role_trans_rule_write(decl->role_tr_rules, fp) == -1 ||
+ role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
return POLICYDB_ERROR;
}
+
+ if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
+ filename_trans_rule_write(decl->filename_trans_rules, fp))
+ return POLICYDB_ERROR;
+
if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
return POLICYDB_ERROR;
@@ -1839,6 +1923,9 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
return POLICYDB_ERROR;
if (role_allow_write(p->role_allow, fp))
return POLICYDB_ERROR;
+ if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS &&
+ filename_trans_write(p->filename_trans, fp))
+ return POLICYDB_ERROR;
} else {
if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
return POLICYDB_ERROR;
[-- Attachment #3: libsepol-rhat.patch.sig --]
[-- Type: application/pgp-signature, Size: 72 bytes --]
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: Here is an updated Eric Paris patch for adding named file trans rules.
2011-04-12 18:35 ` Here is an updated Eric Paris patch for adding named file trans rules Daniel J Walsh
@ 2011-04-12 19:20 ` Steve Lawrence
2011-04-13 2:35 ` Harry Ciao
0 siblings, 1 reply; 8+ messages in thread
From: Steve Lawrence @ 2011-04-12 19:20 UTC (permalink / raw)
To: Daniel J Walsh; +Cc: SELinux, Eric Paris, Harry Ciao
On 04/12/2011 02:35 PM, Daniel J Walsh wrote:
> It also has a fix for the ROLE_TRANS patch from Harry Ciao that was
> blowing up when used with policy less then 26. IE Everywhere.
>
Thanks for the patch. I'm looking into it right now.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Here is an updated Eric Paris patch for adding named file trans rules.
2011-04-12 19:20 ` Steve Lawrence
@ 2011-04-13 2:35 ` Harry Ciao
0 siblings, 0 replies; 8+ messages in thread
From: Harry Ciao @ 2011-04-13 2:35 UTC (permalink / raw)
To: Steve Lawrence; +Cc: Daniel J Walsh, SELinux, Eric Paris
Hi Steve,
Sorry for all problems caused by me not having taken into consideration
the policy.X < 26.
Lesson learned, I am studying the patches from Dan and Eric now, I would
surely be more comprehensive for further SELinux development.
Thanks Dan and Eric for pointing the problems out and proving quick
solutions!
Best regards,
Harry
Steve Lawrence 写道:
> On 04/12/2011 02:35 PM, Daniel J Walsh wrote:
>
>> It also has a fix for the ROLE_TRANS patch from Harry Ciao that was
>> blowing up when used with policy less then 26. IE Everywhere.
>>
>>
>
> Thanks for the patch. I'm looking into it right now.
>
>
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: This patch adds a new subs_dist file.
2011-04-06 21:08 This patch adds a new subs_dist file Daniel J Walsh
2011-04-12 13:33 ` Steve Lawrence
@ 2011-04-18 10:41 ` Richard Haines
2011-04-18 15:23 ` Daniel J Walsh
1 sibling, 1 reply; 8+ messages in thread
From: Richard Haines @ 2011-04-18 10:41 UTC (permalink / raw)
To: Daniel J Walsh; +Cc: SELinux
Dan,
This patch always processes the substitution files (if installed) from the active policy contexts/files/file_contexts.subs and subs_dist irrespective of the backend type or SELABEL_OPT_PATH setting.
Is this what's required ???
If not this patch processes the correct subs files when selabel_open is called with SELABEL_CTX_FILE. The other backends could also process their own substitution files if needed in their own areas.
I've tested with selabel* and matchpathcon functions.
If this patch is okay then I will submit it to the patch queue.
---
libselinux/src/label.c | 4 +---
libselinux/src/label_file.c | 15 +++++++++++++++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index ba316df..7d71e72 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -56,7 +56,7 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src)
return NULL;
}
-static struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
+struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
{
char buf[1024];
FILE *cfg = fopen(path, "r");
@@ -161,8 +161,6 @@ struct selabel_handle *selabel_open(unsigned int backend,
rec->validating = selabel_is_validate_set(opts, nopts);
rec->subs = NULL;
- rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
- rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
if ((*initfuncs[backend])(rec, opts, nopts)) {
free(rec);
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 937e509..619c435 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -395,6 +395,9 @@ static int process_line(struct selabel_handle *rec,
return 0;
}
+/* Used to initialise the substitution files in label.c */
+extern struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list);
+
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned n)
{
@@ -406,6 +409,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
FILE *homedirfp = NULL;
char local_path[PATH_MAX + 1];
char homedir_path[PATH_MAX + 1];
+ char subs_file[PATH_MAX + 1];
char *line_buf = NULL;
size_t line_len = 0;
unsigned int lineno, pass, i, j, maxnspec;
@@ -427,6 +431,17 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
break;
}
+ /* Process local and distribution substitution files */
+ if (!path) {
+ rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
+ rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
+ } else {
+ snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
+ rec->subs = selabel_subs_init(subs_file, rec->subs);
+ snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
+ rec->subs = selabel_subs_init(subs_file, rec->subs);
+ }
+
/* Open the specification file. */
if (!path)
path = selinux_file_context_path();
--
1.7.3.2
Richard
--- On Wed, 6/4/11, Daniel J Walsh <dwalsh@redhat.com> wrote:
> From: Daniel J Walsh <dwalsh@redhat.com>
> Subject: This patch adds a new subs_dist file.
> To: "SELinux" <selinux@tycho.nsa.gov>
> Date: Wednesday, 6 April, 2011, 22:08
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> The idea is to allow distributions to ship a subs file as
> well as let
> the user modify subs.
>
> In F16 we are looking at shipping a
>
> file_contexts.subs_dist file like this
>
> cat file_contexts.subs_dist
> /run /var/run
> /run/lock /var/lock
> /var/run/lock /var/lock
> /lib64 /lib
> /usr/lib64 /usr/lib
>
>
> The we will remove all (64)? from policy.
>
> This will allow us to make sure all /usr/lib/libBLAH is
> labeled the same
> as /usr/lib64/libBLAH
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (GNU/Linux)
> Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAk2c1ksACgkQrlYvE4MpobNXcQCgqgAiQJxmwa1+NdIq8E3tQRp6
> QT0An0ihA60di9CRsEqEdVbSaHOwtte5
> =LXgd
> -----END PGP SIGNATURE-----
>
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: This patch adds a new subs_dist file.
2011-04-18 10:41 ` This patch adds a new subs_dist file Richard Haines
@ 2011-04-18 15:23 ` Daniel J Walsh
0 siblings, 0 replies; 8+ messages in thread
From: Daniel J Walsh @ 2011-04-18 15:23 UTC (permalink / raw)
To: Richard Haines; +Cc: SELinux
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 04/18/2011 06:41 AM, Richard Haines wrote:
>
> Dan,
> This patch always processes the substitution files (if installed) from the active policy contexts/files/file_contexts.subs and subs_dist irrespective of the backend type or SELABEL_OPT_PATH setting.
>
> Is this what's required ???
>
> If not this patch processes the correct subs files when selabel_open is called with SELABEL_CTX_FILE. The other backends could also process their own substitution files if needed in their own areas.
> I've tested with selabel* and matchpathcon functions.
>
> If this patch is okay then I will submit it to the patch queue.
>
Ok with me.
> ---
> libselinux/src/label.c | 4 +---
> libselinux/src/label_file.c | 15 +++++++++++++++
> 2 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/libselinux/src/label.c b/libselinux/src/label.c
> index ba316df..7d71e72 100644
> --- a/libselinux/src/label.c
> +++ b/libselinux/src/label.c
> @@ -56,7 +56,7 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src)
> return NULL;
> }
>
> -static struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
> +struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
> {
> char buf[1024];
> FILE *cfg = fopen(path, "r");
> @@ -161,8 +161,6 @@ struct selabel_handle *selabel_open(unsigned int backend,
> rec->validating = selabel_is_validate_set(opts, nopts);
>
> rec->subs = NULL;
> - rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
> - rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
>
> if ((*initfuncs[backend])(rec, opts, nopts)) {
> free(rec);
> diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
> index 937e509..619c435 100644
> --- a/libselinux/src/label_file.c
> +++ b/libselinux/src/label_file.c
> @@ -395,6 +395,9 @@ static int process_line(struct selabel_handle *rec,
> return 0;
> }
>
> +/* Used to initialise the substitution files in label.c */
> +extern struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list);
> +
> static int init(struct selabel_handle *rec, struct selinux_opt *opts,
> unsigned n)
> {
> @@ -406,6 +409,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
> FILE *homedirfp = NULL;
> char local_path[PATH_MAX + 1];
> char homedir_path[PATH_MAX + 1];
> + char subs_file[PATH_MAX + 1];
> char *line_buf = NULL;
> size_t line_len = 0;
> unsigned int lineno, pass, i, j, maxnspec;
> @@ -427,6 +431,17 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
> break;
> }
>
> + /* Process local and distribution substitution files */
> + if (!path) {
> + rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
> + rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
> + } else {
> + snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
> + rec->subs = selabel_subs_init(subs_file, rec->subs);
> + snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
> + rec->subs = selabel_subs_init(subs_file, rec->subs);
> + }
> +
> /* Open the specification file. */
> if (!path)
> path = selinux_file_context_path();
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk2sV1cACgkQrlYvE4MpobPhzQCgmVjrSAzoURt1vXGJ/b5EohMJ
OWEAoNVQjouqUPvn2acPNTAxxlKcvcOw
=k5qu
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-04-18 15:23 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-06 21:08 This patch adds a new subs_dist file Daniel J Walsh
2011-04-12 13:33 ` Steve Lawrence
2011-04-12 16:12 ` Daniel J Walsh
2011-04-12 18:35 ` Here is an updated Eric Paris patch for adding named file trans rules Daniel J Walsh
2011-04-12 19:20 ` Steve Lawrence
2011-04-13 2:35 ` Harry Ciao
2011-04-18 10:41 ` This patch adds a new subs_dist file Richard Haines
2011-04-18 15:23 ` Daniel J Walsh
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.