selinux: declare data arrays const

The arrays for the policy capability names, the initial sid identifiers
and the class and permission names are not changed at runtime.  Declare
them const to avoid accidental modification.

Do not override the classmap and the initial sid list in the build time
script genheaders.

Check flose(3) is successful in genheaders.c, otherwise the written data
might be corrupted or incomplete.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
[PM: manual merge due to fuzz, minor style tweaks]
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Christian Göttsche 2022-05-02 16:43:38 +02:00 committed by Paul Moore
parent a9029d9704
commit ded34574d4
11 changed files with 71 additions and 58 deletions

View File

@ -59,35 +59,27 @@ int main(int argc, char *argv[])
exit(2); exit(2);
} }
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
map->name = stoupperx(map->name);
for (j = 0; map->perms[j]; j++)
map->perms[j] = stoupperx(map->perms[j]);
}
isids_len = sizeof(initial_sid_to_string) / sizeof (char *);
for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i];
if (s)
initial_sid_to_string[i] = stoupperx(s);
}
fprintf(fout, "/* This file is automatically generated. Do not edit. */\n"); fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n"); fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n");
for (i = 0; secclass_map[i].name; i++) { for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i]; char *name = stoupperx(secclass_map[i].name);
fprintf(fout, "#define SECCLASS_%-39s %2d\n", map->name, i+1);
fprintf(fout, "#define SECCLASS_%-39s %2d\n", name, i+1);
free(name);
} }
fprintf(fout, "\n"); fprintf(fout, "\n");
isids_len = sizeof(initial_sid_to_string) / sizeof(char *);
for (i = 1; i < isids_len; i++) { for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i]; const char *s = initial_sid_to_string[i];
if (s) if (s) {
fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i); char *sidname = stoupperx(s);
fprintf(fout, "#define SECINITSID_%-39s %2d\n", sidname, i);
free(sidname);
}
} }
fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n"); fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n");
@ -96,10 +88,14 @@ int main(int argc, char *argv[])
fprintf(fout, "\tswitch (kern_tclass) {\n"); fprintf(fout, "\tswitch (kern_tclass) {\n");
for (i = 0; secclass_map[i].name; i++) { for (i = 0; secclass_map[i].name; i++) {
static char s[] = "SOCKET"; static char s[] = "SOCKET";
struct security_class_mapping *map = &secclass_map[i]; int len, l;
int len = strlen(map->name), l = sizeof(s) - 1; char *name = stoupperx(secclass_map[i].name);
if (len >= l && memcmp(map->name + len - l, s, l) == 0)
fprintf(fout, "\tcase SECCLASS_%s:\n", map->name); len = strlen(name);
l = sizeof(s) - 1;
if (len >= l && memcmp(name + len - l, s, l) == 0)
fprintf(fout, "\tcase SECCLASS_%s:\n", name);
free(name);
} }
fprintf(fout, "\t\tsock = true;\n"); fprintf(fout, "\t\tsock = true;\n");
fprintf(fout, "\t\tbreak;\n"); fprintf(fout, "\t\tbreak;\n");
@ -110,33 +106,52 @@ int main(int argc, char *argv[])
fprintf(fout, "}\n"); fprintf(fout, "}\n");
fprintf(fout, "\n#endif\n"); fprintf(fout, "\n#endif\n");
fclose(fout);
if (fclose(fout) != 0) {
fprintf(stderr, "Could not successfully close %s: %s\n",
argv[1], strerror(errno));
exit(4);
}
fout = fopen(argv[2], "w"); fout = fopen(argv[2], "w");
if (!fout) { if (!fout) {
fprintf(stderr, "Could not open %s for writing: %s\n", fprintf(stderr, "Could not open %s for writing: %s\n",
argv[2], strerror(errno)); argv[2], strerror(errno));
exit(4); exit(5);
} }
fprintf(fout, "/* This file is automatically generated. Do not edit. */\n"); fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n"); fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n");
for (i = 0; secclass_map[i].name; i++) { for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i]; const struct security_class_mapping *map = &secclass_map[i];
int len = strlen(map->name); int len;
char *name = stoupperx(map->name);
len = strlen(name);
for (j = 0; map->perms[j]; j++) { for (j = 0; map->perms[j]; j++) {
char *permname;
if (j >= 32) { if (j >= 32) {
fprintf(stderr, "Too many permissions to fit into an access vector at (%s, %s).\n", fprintf(stderr, "Too many permissions to fit into an access vector at (%s, %s).\n",
map->name, map->perms[j]); map->name, map->perms[j]);
exit(5); exit(5);
} }
fprintf(fout, "#define %s__%-*s 0x%08xU\n", map->name, permname = stoupperx(map->perms[j]);
39-len, map->perms[j], 1U<<j); fprintf(fout, "#define %s__%-*s 0x%08xU\n", name,
39-len, permname, 1U<<j);
free(permname);
} }
free(name);
} }
fprintf(fout, "\n#endif\n"); fprintf(fout, "\n#endif\n");
fclose(fout);
if (fclose(fout) != 0) {
fprintf(stderr, "Could not successfully close %s: %s\n",
argv[2], strerror(errno));
exit(6);
}
exit(0); exit(0);
} }

View File

@ -82,7 +82,7 @@ int main(int argc, char *argv[])
/* print out the class permissions */ /* print out the class permissions */
for (i = 0; secclass_map[i].name; i++) { for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i]; const struct security_class_mapping *map = &secclass_map[i];
fprintf(fout, "class %s\n", map->name); fprintf(fout, "class %s\n", map->name);
fprintf(fout, "{\n"); fprintf(fout, "{\n");
for (j = 0; map->perms[j]; j++) for (j = 0; map->perms[j]; j++)
@ -103,7 +103,7 @@ int main(int argc, char *argv[])
#define SYSTEMLOW "s0" #define SYSTEMLOW "s0"
#define SYSTEMHIGH "s1:c0.c1" #define SYSTEMHIGH "s1:c0.c1"
for (i = 0; secclass_map[i].name; i++) { for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i]; const struct security_class_mapping *map = &secclass_map[i];
fprintf(fout, "mlsconstrain %s {\n", map->name); fprintf(fout, "mlsconstrain %s {\n", map->name);
for (j = 0; map->perms[j]; j++) for (j = 0; map->perms[j]; j++)

View File

@ -668,7 +668,7 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
struct common_audit_data *ad = a; struct common_audit_data *ad = a;
struct selinux_audit_data *sad = ad->selinux_audit_data; struct selinux_audit_data *sad = ad->selinux_audit_data;
u32 av = sad->audited; u32 av = sad->audited;
const char **perms; const char *const *perms;
int i, perm; int i, perm;
audit_log_format(ab, "avc: %s ", sad->denied ? "denied" : "granted"); audit_log_format(ab, "avc: %s ", sad->denied ? "denied" : "granted");

View File

@ -18,7 +18,7 @@ struct security_class_mapping {
const char *perms[sizeof(u32) * 8 + 1]; const char *perms[sizeof(u32) * 8 + 1];
}; };
extern struct security_class_mapping secclass_map[]; extern const struct security_class_mapping secclass_map[];
#endif /* _SELINUX_AVC_SS_H_ */ #endif /* _SELINUX_AVC_SS_H_ */

View File

@ -38,7 +38,7 @@
* Note: The name for any socket class should be suffixed by "socket", * Note: The name for any socket class should be suffixed by "socket",
* and doesn't contain more than one substr of "socket". * and doesn't contain more than one substr of "socket".
*/ */
struct security_class_mapping secclass_map[] = { const struct security_class_mapping secclass_map[] = {
{ "security", { "security",
{ "compute_av", "compute_create", "compute_member", { "compute_av", "compute_create", "compute_member",
"check_context", "load_policy", "compute_relabel", "check_context", "load_policy", "compute_relabel",

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
static const char *initial_sid_to_string[] = { static const char *const initial_sid_to_string[] = {
NULL, NULL,
"kernel", "kernel",
"security", "security",

View File

@ -16,6 +16,6 @@ enum {
}; };
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)
extern const char *selinux_policycap_names[__POLICYDB_CAP_MAX]; extern const char *const selinux_policycap_names[__POLICYDB_CAP_MAX];
#endif /* _SELINUX_POLICYCAP_H_ */ #endif /* _SELINUX_POLICYCAP_H_ */

View File

@ -5,7 +5,7 @@
#include "policycap.h" #include "policycap.h"
/* Policy capability names */ /* Policy capability names */
const char *selinux_policycap_names[__POLICYDB_CAP_MAX] = { const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = {
"network_peer_controls", "network_peer_controls",
"open_perms", "open_perms",
"extended_socket_class", "extended_socket_class",

View File

@ -385,7 +385,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
chain2_len_sum); chain2_len_sum);
} }
static uint16_t spec_order[] = { static const uint16_t spec_order[] = {
AVTAB_ALLOWED, AVTAB_ALLOWED,
AVTAB_AUDITDENY, AVTAB_AUDITDENY,
AVTAB_AUDITALLOW, AVTAB_AUDITALLOW,

View File

@ -61,7 +61,7 @@ struct policydb_compat_info {
}; };
/* These need to be updated if SYM_NUM or OCON_NUM changes */ /* These need to be updated if SYM_NUM or OCON_NUM changes */
static struct policydb_compat_info policydb_compat[] = { static const struct policydb_compat_info policydb_compat[] = {
{ {
.version = POLICYDB_VERSION_BASE, .version = POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM - 3, .sym_num = SYM_NUM - 3,
@ -159,18 +159,16 @@ static struct policydb_compat_info policydb_compat[] = {
}, },
}; };
static struct policydb_compat_info *policydb_lookup_compat(int version) static const struct policydb_compat_info *policydb_lookup_compat(int version)
{ {
int i; int i;
struct policydb_compat_info *info = NULL;
for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) { for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
if (policydb_compat[i].version == version) { if (policydb_compat[i].version == version)
info = &policydb_compat[i]; return &policydb_compat[i];
break;
}
} }
return info;
return NULL;
} }
/* /*
@ -314,7 +312,7 @@ static int cat_destroy(void *key, void *datum, void *p)
return 0; return 0;
} }
static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = { static int (*const destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = {
common_destroy, common_destroy,
cls_destroy, cls_destroy,
role_destroy, role_destroy,
@ -669,7 +667,7 @@ static int cat_index(void *key, void *datum, void *datap)
return 0; return 0;
} }
static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = { static int (*const index_f[SYM_NUM]) (void *key, void *datum, void *datap) = {
common_index, common_index,
class_index, class_index,
role_index, role_index,
@ -1637,7 +1635,8 @@ bad:
return rc; return rc;
} }
static int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) = { static int (*const read_f[SYM_NUM]) (struct policydb *p,
struct symtab *s, void *fp) = {
common_read, common_read,
class_read, class_read,
role_read, role_read,
@ -2208,7 +2207,7 @@ out:
return rc; return rc;
} }
static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, static int ocontext_read(struct policydb *p, const struct policydb_compat_info *info,
void *fp) void *fp)
{ {
int i, j, rc; int i, j, rc;
@ -2404,7 +2403,7 @@ int policydb_read(struct policydb *p, void *fp)
u32 len, nprim, nel, perm; u32 len, nprim, nel, perm;
char *policydb_str; char *policydb_str;
struct policydb_compat_info *info; const struct policydb_compat_info *info;
policydb_init(p); policydb_init(p);
@ -3238,8 +3237,7 @@ static int user_write(void *vkey, void *datum, void *ptr)
return 0; return 0;
} }
static int (*write_f[SYM_NUM]) (void *key, void *datum, static int (*const write_f[SYM_NUM]) (void *key, void *datum, void *datap) = {
void *datap) = {
common_write, common_write,
class_write, class_write,
role_write, role_write,
@ -3250,7 +3248,7 @@ static int (*write_f[SYM_NUM]) (void *key, void *datum,
cat_write, cat_write,
}; };
static int ocontext_write(struct policydb *p, struct policydb_compat_info *info, static int ocontext_write(struct policydb *p, const struct policydb_compat_info *info,
void *fp) void *fp)
{ {
unsigned int i, j, rc; unsigned int i, j, rc;
@ -3607,7 +3605,7 @@ int policydb_write(struct policydb *p, void *fp)
__le32 buf[4]; __le32 buf[4];
u32 config; u32 config;
size_t len; size_t len;
struct policydb_compat_info *info; const struct policydb_compat_info *info;
/* /*
* refuse to write policy older than compressed avtab * refuse to write policy older than compressed avtab

View File

@ -99,7 +99,7 @@ static void context_struct_compute_av(struct policydb *policydb,
struct extended_perms *xperms); struct extended_perms *xperms);
static int selinux_set_mapping(struct policydb *pol, static int selinux_set_mapping(struct policydb *pol,
struct security_class_mapping *map, const struct security_class_mapping *map,
struct selinux_map *out_map) struct selinux_map *out_map)
{ {
u16 i, j; u16 i, j;
@ -121,7 +121,7 @@ static int selinux_set_mapping(struct policydb *pol,
/* Store the raw class and permission values */ /* Store the raw class and permission values */
j = 0; j = 0;
while (map[j].name) { while (map[j].name) {
struct security_class_mapping *p_in = map + (j++); const struct security_class_mapping *p_in = map + (j++);
struct selinux_mapping *p_out = out_map->mapping + j; struct selinux_mapping *p_out = out_map->mapping + j;
/* An empty class string skips ahead */ /* An empty class string skips ahead */