diff options
Diffstat (limited to 'libselinux')
-rw-r--r-- | libselinux/include/selinux/label.h | 12 | ||||
-rw-r--r-- | libselinux/include/selinux/selinux.h | 1 | ||||
-rw-r--r-- | libselinux/man/man3/selabel_open.3 | 10 | ||||
-rw-r--r-- | libselinux/man/man3/selinux_binary_policy_path.3 | 4 | ||||
-rw-r--r-- | libselinux/man/man5/selabel_db.5 | 93 | ||||
-rw-r--r-- | libselinux/src/file_path_suffixes.h | 1 | ||||
-rw-r--r-- | libselinux/src/label.c | 3 | ||||
-rw-r--r-- | libselinux/src/label_db.c | 336 | ||||
-rw-r--r-- | libselinux/src/label_internal.h | 2 | ||||
-rw-r--r-- | libselinux/src/selinux_config.c | 9 | ||||
-rw-r--r-- | libselinux/src/selinux_internal.h | 1 |
11 files changed, 467 insertions, 5 deletions
diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h index 82f4e13c..04353652 100644 --- a/libselinux/include/selinux/label.h +++ b/libselinux/include/selinux/label.h @@ -29,6 +29,8 @@ struct selabel_handle; #define SELABEL_CTX_MEDIA 1 /* x contexts */ #define SELABEL_CTX_X 2 +/* db objects */ +#define SELABEL_CTX_DB 3 /* * Available options @@ -116,6 +118,16 @@ void selabel_stats(struct selabel_handle *handle); #define SELABEL_X_POLYPROP 6 #define SELABEL_X_POLYSELN 7 +/* DB backend */ +#define SELABEL_DB_DATABASE 1 +#define SELABEL_DB_SCHEMA 2 +#define SELABEL_DB_TABLE 3 +#define SELABEL_DB_COLUMN 4 +#define SELABEL_DB_SEQUENCE 5 +#define SELABEL_DB_VIEW 6 +#define SELABEL_DB_PROCEDURE 7 +#define SELABEL_DB_BLOB 8 +#define SELABEL_DB_TUPLE 9 #ifdef __cplusplus } diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index cacb3cb1..834a1ee0 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -487,6 +487,7 @@ extern const char *selinux_media_context_path(void); extern const char *selinux_virtual_domain_context_path(void); extern const char *selinux_virtual_image_context_path(void); extern const char *selinux_x_context_path(void); +extern const char *selinux_sepgsql_context_path(void); extern const char *selinux_contexts_path(void); extern const char *selinux_securetty_types_path(void); extern const char *selinux_booleans_path(void); diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3 index 1af2ec02..8674e377 100644 --- a/libselinux/man/man3/selabel_open.3 +++ b/libselinux/man/man3/selabel_open.3 @@ -72,15 +72,19 @@ Note that an invalid context may not be treated as an error unless it is actuall .TP .B SELABEL_CTX_FILE File contexts backend, described in -.BR selabel_file (3). +.BR selabel_file (5). .TP .B SELABEL_CTX_MEDIA Media contexts backend, described in -.BR selabel_media (3). +.BR selabel_media (5). .TP .B SELABEL_CTX_X X Windows contexts backend, described in -.BR selabel_x (3). +.BR selabel_x (5). +.TP +.B SELABEL_CTX_DB +Database objects contexts backend, described in +.BR selabel_db (5). .SH "RETURN VALUE" A non-NULL handle value is returned on success. On error, NULL is returned and diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3 index 61909576..8ead1a44 100644 --- a/libselinux/man/man3/selinux_binary_policy_path.3 +++ b/libselinux/man/man3/selinux_binary_policy_path.3 @@ -29,6 +29,8 @@ extern const char *selinux_usersconf_path(void); extern const char *selinux_x_context_path(void); +extern const char *selinux_sepgsql_context_path(void); + extern const char *selinux_file_context_path(void); extern const char *selinux_media_context_path(void); @@ -66,6 +68,8 @@ selinux_usersconf_path() - file containing mapping between Linux Users and SELin .sp selinux_x_context_path() - file containing configuration for XSELinux extension .sp +selinux_sepgsql_context_path() - file containing configuration for SE-PostgreSQL +.sp selinux_netfilter_context_path - default netfilter context .sp selinux_file_context_path() - default system file contexts configuration diff --git a/libselinux/man/man5/selabel_db.5 b/libselinux/man/man5/selabel_db.5 new file mode 100644 index 00000000..b699f399 --- /dev/null +++ b/libselinux/man/man5/selabel_db.5 @@ -0,0 +1,93 @@ +.\" Hey Emacs! This file is -*- nroff -*- source. +.\" +.\" Author: KaiGai Kohei <kaigai@ak.jp.nec.com> 2009 +.TH "selabel_db" "5" "22 Nov 2009" "" "SELinux API documentation" +.SH "NAME" +selabel_db \- userspace SELinux labeling interface: DB objects contexts backend. +.SH "SYNOPSIS" +.B #include <selinux/selinux.h> + +.B #include <selinux/label.h> +.sp +.BI "int selabel_lookup(struct selabel_handle *" hnd , +.in +\w'int selabel_lookup('u +.BI "security_context_t *" context , + +.BI "const char *" object_name ", int " object_type ");" + +.SH "DESCRIPTION" +The DB contexts backend maps from a pair of object name and class into security contexts. It is used to find the appropriate context for database objects when relabeling a certain database. + +The +.I object_name +should be fully qualified name using the hierarchy of database objects. +For example, the +.B pg_class +table in the +.B postgres +database and +.B pg_catalog +schema should be qualified as +.B postgres.pg_catalog.pg_class . + +The +.I object_type +argument should be set to one of the following values: +.TP +.B SELABEL_DB_DATABASE +The +.I object_name +argument specifies the name of a database itself, such as "postgres". +.TP +.B SELABEL_DB_SCHEMA +The +.I object_name +argument specifies the name of a schema object, such as "postgres.public". +.TP +.B SELABEL_DB_TABLE +The +.I object_name +argument specifies the name of a table object, such as "postgres.public.my_table" +.TP +.B SELABEL_DB_COLUMN +The +.I object_name +argument specifies the name of a column object, such as "postgres.public.my_table.user_id" +.TP +.B SELABEL_DB_TUPLE +The +.I object_name +argument specifies the name of a table object which contains the tuples to be relabeled, such as "postgresql.public.my_table". Note that we have no way to identify individual tuple objects, except for WHERE clause on DML statements, because it has no name. +.TP +.B SELABEL_DB_PROCEDURE +The +.I object_name +argument specifies the name of a procedure object, such as "postgres.public.my_func". Note that we don't support to lookup individual security contexts for each procedures which have same name but different arguments. +.TP +.B SELABEL_DB_SEQUENCE +The +.I object_name +argument specifies the name of a sequence object, such as "postgres.public.my_seq". +.TP +.B SELABEL_DB_BLOB +The +.I object_name +argument specifies the name of a large object, such as "postgres.16308". +Note that a large object does not have its name, so it is identified by its identifier value. + +.SH "OPTIONS" +In addition to the global options described in +.BR selabel_open (3), +this backend recognizes the following options: + +.TP +.B SELABEL_OPT_PATH +A non-null value for this option specifies a path to a file that will be opened in lieu of the standard DB contexts file. +It tries to open the specfile designed for SE-PostgreSQL in the default, so if another RDBMS uses this interface, it needs to give an explicit specfile designed for the RDBMS. + +.SH "SEE ALSO" +.BR selabel_open (3), +.BR selabel_lookup (3), +.BR selabel_stats (3), +.BR selinux (8) + diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h index eada2329..ccf43e15 100644 --- a/libselinux/src/file_path_suffixes.h +++ b/libselinux/src/file_path_suffixes.h @@ -23,3 +23,4 @@ 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_(SEPGSQL_CONTEXTS, "/contexts/sepgsql_contexts") diff --git a/libselinux/src/label.c b/libselinux/src/label.c index cea3c432..020b803d 100644 --- a/libselinux/src/label.c +++ b/libselinux/src/label.c @@ -22,7 +22,8 @@ typedef int (*selabel_initfunc)(struct selabel_handle *rec, static selabel_initfunc initfuncs[] = { &selabel_file_init, &selabel_media_init, - &selabel_x_init + &selabel_x_init, + &selabel_db_init, }; typedef struct selabel_sub { diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c new file mode 100644 index 00000000..e1bfab78 --- /dev/null +++ b/libselinux/src/label_db.c @@ -0,0 +1,336 @@ +/* + * Media contexts backend for DB objects + * + * Author: KaiGai Kohei <kaigai@ak.jp.nec.com> + */ + +#include <sys/stat.h> +#include <string.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <fnmatch.h> +#include "callbacks.h" +#include "label_internal.h" + +/* + * Regular database object's security context interface + * + * It provides applications a regular security context for the given + * database objects. The pair of object's name and a security context + * are described in the specfile. In the default, it shall be stored + * in the /etc/selinux/$POLICYTYPE/contexts/sepgsql_contexts . + * (It assumes SE-PostgreSQL in the default. For other RDBMS, use the + * SELABEL_OPT_PATH option to specify different specfile.) + * + * Each line has the following format: + * <object class> <object name/identifier> <security context> + * + * For example: + * ---------------------------------------- + * # + * # It is an example specfile for database obejcts + * # + * db_database template1 system_u:object_r:sepgsql_db_t:s0 + * + * db_schema *.pg_catalog system_u:object_r:sepgsql_sys_schema_t:s0 + * + * db_table *.pg_catalog.* system_u:object_r:sepgsql_sysobj_t:s0 + * db_column *.pg_catalog.*.* system_u:object_r:sepgsql_sysobj_t:s0 + * ---------------------------------------- + * + * All the characters after the '#' are dealt as comments. + * + * The first token is object class. SELABEL_DB_* declared in label.h are + * corresponding to a certain database object. + * + * The object name/identifier is compared to the given key. + * A database object can have its own namespace hierarchy. + * In the case of SE-PgSQL, database is the top level object, and schema + * is deployed just under a database. A schema can contains various kind + * of objects, such as tables, procedures and so on. + * Thus, when we lookup an expected security context for a table of + * "pg_class", it is necessary to assume selabel_lookup() is called with + * "postgres.pg_catalog.pg_class", not just a "pg_class". + * + * Wildcards ('*' or '?') are available on the patterns, so if you want + * to match a table within any schema, you should set '*' on the upper + * namespaces of the table. + * + * The structure of namespace depends on RDBMS. + * For example, Trusted-RUBIX has an idea of "catalog" which performs + * as a namespace between a database and individual schemas. In this + * case, a table has upper three layers. + */ + +/* + * spec_t : It holds a pair of a key and an expected security context + */ +typedef struct spec { + struct selabel_lookup_rec lr; + char *key; + int type; + int matches; +} spec_t; + +/* + * catalog_t : An array of spec_t + */ +typedef struct catalog { + unsigned int nspec; /* number of specs in use */ + unsigned int limit; /* physical limitation of specs[] */ + spec_t specs[0]; +} catalog_t; + +/* + * Helper function to parse a line read from the specfile + */ +static int +process_line(const char *path, char *line_buf, unsigned int line_num, + catalog_t *catalog) +{ + spec_t *spec = &catalog->specs[catalog->nspec]; + char *type, *key, *context, *temp; + int items; + + /* Cut off comments */ + temp = strchr(line_buf, '#'); + if (temp) + *temp = '\0'; + + /* + * Every entry must have the following format + * <object class> <object name> <security context> + */ + type = key = context = temp = NULL; + items = sscanf(line_buf, "%as %as %as %as", + &type, &key, &context, &temp); + if (items != 3) { + if (items > 0) + selinux_log(SELINUX_WARNING, + "%s: line %d has invalid format, skipped", + path, line_num); + goto skip; + } + + /* + * Set up individual spec entry + */ + memset(spec, 0, sizeof(spec_t)); + + if (!strcmp(type, "db_database")) + spec->type = SELABEL_DB_DATABASE; + else if (!strcmp(type, "db_schema")) + spec->type = SELABEL_DB_SCHEMA; + else if (!strcmp(type, "db_table")) + spec->type = SELABEL_DB_TABLE; + else if (!strcmp(type, "db_column")) + spec->type = SELABEL_DB_COLUMN; + else if (!strcmp(type, "db_sequence")) + spec->type = SELABEL_DB_SEQUENCE; + else if (!strcmp(type, "db_view")) + spec->type = SELABEL_DB_VIEW; + else if (!strcmp(type, "db_procedure")) + spec->type = SELABEL_DB_PROCEDURE; + else if (!strcmp(type, "db_blob")) + spec->type = SELABEL_DB_BLOB; + else if (!strcmp(type, "db_tuple")) + spec->type = SELABEL_DB_TUPLE; + else { + selinux_log(SELINUX_WARNING, + "%s: line %d has invalid object type %s\n", + path, line_num, type); + goto skip; + } + + free(type); + spec->key = key; + spec->lr.ctx_raw = context; + + catalog->nspec++; + + return 0; + +skip: + free(type); + free(key); + free(context); + free(temp); + + return 0; +} + +/* + * selabel_close() handler + */ +static void +db_close(struct selabel_handle *rec) +{ + catalog_t *catalog = (catalog_t *)rec->data; + spec_t *spec; + unsigned int i; + + for (i = 0; i < catalog->nspec; i++) { + spec = &catalog->specs[i]; + free(spec->key); + free(spec->lr.ctx_raw); + free(spec->lr.ctx_trans); + } + free(catalog); +} + +/* + * selabel_lookup() handler + */ +static struct selabel_lookup_rec * +db_lookup(struct selabel_handle *rec, const char *key, int type) +{ + catalog_t *catalog = (catalog_t *)rec->data; + spec_t *spec; + unsigned int i; + + for (i = 0; i < catalog->nspec; i++) { + spec = &catalog->specs[i]; + + if (spec->type != type) + continue; + if (!fnmatch(spec->key, key, 0)) { + spec->matches++; + + return &spec->lr; + } + } + + /* No found */ + errno = ENOENT; + return NULL; +} + +/* + * selabel_stats() handler + */ +static void +db_stats(struct selabel_handle *rec) +{ + catalog_t *catalog = (catalog_t *)rec->data; + unsigned int i, total = 0; + + for (i = 0; i < catalog->nspec; i++) + total += catalog->specs[i].matches; + + selinux_log(SELINUX_INFO, "%u entries, %u matches made\n", + catalog->nspec, total); +} + +/* + * selabel_open() handler + */ +static catalog_t * +db_init(struct selinux_opt *opts, unsigned nopts) +{ + catalog_t *catalog; + FILE *filp; + const char *path = NULL; + char *line_buf = NULL; + size_t line_len = 0; + unsigned int line_num = 0; + unsigned int i; + + /* + * Initialize catalog data structure + */ + catalog = malloc(sizeof(catalog_t) + 32 * sizeof(spec_t)); + if (!catalog) + return NULL; + catalog->limit = 32; + catalog->nspec = 0; + + /* + * Process arguments + * + * SELABEL_OPT_PATH: + * It allows to specify an alternative specification file instead of + * the default one. If RDBMS is not SE-PostgreSQL, it may need to + * specify an explicit specfile for database objects. + */ + while (nopts--) { + switch (opts[nopts].type) { + case SELABEL_OPT_PATH: + path = opts[nopts].value; + break; + } + } + + /* + * Open the specification file + */ + if (!path) + path = selinux_sepgsql_context_path(); + + if ((filp = fopen(path, "rb")) == NULL) { + free(catalog); + return NULL; + } + + /* + * Parse for each lines + */ + while (getline(&line_buf, &line_len, filp) > 0) { + /* + * Expand catalog array, if necessary + */ + if (catalog->limit == catalog->nspec) { + size_t length; + unsigned int new_limit = 2 * catalog->limit; + catalog_t *new_catalog; + + length = sizeof(catalog_t) + + new_limit * sizeof(spec_t); + new_catalog = realloc(catalog, length); + if (!new_catalog) + goto out_error; + + catalog = new_catalog; + catalog->limit = new_limit; + } + + /* + * Parse a line + */ + if (process_line(path, line_buf, ++line_num, catalog) < 0) + goto out_error; + } + free(line_buf); + + fclose(filp); + + return catalog; + +out_error: + for (i = 0; i < catalog->nspec; i++) { + spec_t *spec = &catalog->specs[i]; + + free(spec->key); + free(spec->lr.ctx_raw); + free(spec->lr.ctx_trans); + } + free(catalog); + + return NULL; +} + +/* + * Initialize selabel_handle and load the entries of specfile + */ +int selabel_db_init(struct selabel_handle *rec, + struct selinux_opt *opts, unsigned nopts) +{ + rec->func_close = &db_close; + rec->func_lookup = &db_lookup; + rec->func_stats = &db_stats; + rec->data = db_init(opts, nopts); + + return !rec->data ? -1 : 0; +} diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h index 27a1f06a..99af93e8 100644 --- a/libselinux/src/label_internal.h +++ b/libselinux/src/label_internal.h @@ -23,6 +23,8 @@ int selabel_media_init(struct selabel_handle *rec, struct selinux_opt *opts, unsigned nopts) hidden; int selabel_x_init(struct selabel_handle *rec, struct selinux_opt *opts, unsigned nopts) hidden; +int selabel_db_init(struct selabel_handle *rec, + struct selinux_opt *opts, unsigned nopts) hidden; /* * Labeling internal structures diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c index 7e588cc0..e0409597 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -44,7 +44,8 @@ #define VIRTUAL_DOMAIN 21 #define VIRTUAL_IMAGE 22 #define FILE_CONTEXT_SUBS 23 -#define NEL 24 +#define SEPGSQL_CONTEXTS 24 +#define NEL 25 /* Part of one-time lazy init */ static pthread_once_t once = PTHREAD_ONCE_INIT; @@ -422,3 +423,9 @@ const char * selinux_file_context_subs_path(void) { hidden_def(selinux_file_context_subs_path) +const char *selinux_sepgsql_context_path() +{ + return get_path(SEPGSQL_CONTEXTS); +} + +hidden_def(selinux_sepgsql_context_path) diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index 88b6bd63..24ef21ad 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -73,6 +73,7 @@ hidden_proto(selinux_mkload_policy) hidden_proto(selinux_customizable_types_path) hidden_proto(selinux_media_context_path) hidden_proto(selinux_x_context_path) + hidden_proto(selinux_sepgsql_context_path) hidden_proto(selinux_path) hidden_proto(selinux_check_passwd_access) hidden_proto(selinux_check_securetty_context) |