diff mbox series

libsepol,checkpolicy: remove use of hardcoded security class values

Message ID 20200116200136.19687-1-sds@tycho.nsa.gov (mailing list archive)
State Superseded
Headers show
Series libsepol,checkpolicy: remove use of hardcoded security class values | expand

Commit Message

Stephen Smalley Jan. 16, 2020, 8:01 p.m. UTC
libsepol carried its own (outdated) copy of flask.h with the generated
security class and initial SID values for use by the policy
compiler and the forked copy of the security server code
leveraged by tools such as audit2why.  Convert libsepol and
checkpolicy entirely to looking up class values from the policy,
remove the SECCLASS_* definitions from its flask.h header, and move
the header with its remaining initial SID definitions private to
libsepol.  While we are here, fix the sepol_compute_sid() logic to
properly support features long since added to the policy and kernel,
although there are no users of it other than checkpolicy -d (debug)
and it is not exported to users of the shared library.  There
are still some residual differences between the kernel logic and
libsepol.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
---
 checkpolicy/checkmodule.c                     |  1 -
 checkpolicy/checkpolicy.c                     |  1 -
 checkpolicy/policy_define.c                   | 26 +++--
 checkpolicy/policy_parse.y                    |  1 -
 checkpolicy/test/dismod.c                     |  1 -
 libsepol/cil/src/cil_binary.c                 |  1 -
 libsepol/include/sepol/policydb/flask.h       | 94 -------------------
 libsepol/include/sepol/policydb/flask_types.h |  4 +-
 libsepol/include/sepol/policydb/policydb.h    |  5 +
 libsepol/src/flask.h                          | 38 ++++++++
 libsepol/src/kernel_to_cil.c                  |  1 -
 libsepol/src/kernel_to_conf.c                 |  1 -
 libsepol/src/mls.c                            |  3 +-
 libsepol/src/policydb.c                       | 70 +++++++++++++-
 libsepol/src/services.c                       | 87 ++++++++++-------
 libsepol/src/sidtab.c                         |  2 +-
 libsepol/src/write.c                          | 25 +++--
 17 files changed, 196 insertions(+), 165 deletions(-)
 delete mode 100644 libsepol/include/sepol/policydb/flask.h
 create mode 100644 libsepol/src/flask.h

Comments

Stephen Smalley Jan. 16, 2020, 8:34 p.m. UTC | #1
On 1/16/20 3:01 PM, Stephen Smalley wrote:
> libsepol carried its own (outdated) copy of flask.h with the generated
> security class and initial SID values for use by the policy
> compiler and the forked copy of the security server code
> leveraged by tools such as audit2why.  Convert libsepol and
> checkpolicy entirely to looking up class values from the policy,
> remove the SECCLASS_* definitions from its flask.h header, and move
> the header with its remaining initial SID definitions private to
> libsepol.  While we are here, fix the sepol_compute_sid() logic to
> properly support features long since added to the policy and kernel,
> although there are no users of it other than checkpolicy -d (debug)
> and it is not exported to users of the shared library.  There
> are still some residual differences between the kernel logic and
> libsepol.
> 
> Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>

I see that this fails travis-ci; looks like the problem is that it 
trades using hardcoded values for SECCLASS_PROCESS and _DIR and the 
PROCESS__TRANSITION/DYNTRANSITION permissions for requiring the strings 
to be present in the policy and that isn't true of some test policies. 
The kernel does require at least the process class and perms to be 
present or it will reject the policy at load time presently (when it was 
likewise converted long ago as part of dynamic class/perm support). 
Options:
- Weaken the restrictions in libsepol's policydb_read and accept the 
fact that the class/perm values may be zero subsequently within libsepol.
- Change the test policies to at least provide this minimal set.

The "dir" class isn't currently mapped at load time by the kernel but it 
unmaps it for genfs_sid() matching so it still expects it to be present.

> ---
>   checkpolicy/checkmodule.c                     |  1 -
>   checkpolicy/checkpolicy.c                     |  1 -
>   checkpolicy/policy_define.c                   | 26 +++--
>   checkpolicy/policy_parse.y                    |  1 -
>   checkpolicy/test/dismod.c                     |  1 -
>   libsepol/cil/src/cil_binary.c                 |  1 -
>   libsepol/include/sepol/policydb/flask.h       | 94 -------------------
>   libsepol/include/sepol/policydb/flask_types.h |  4 +-
>   libsepol/include/sepol/policydb/policydb.h    |  5 +
>   libsepol/src/flask.h                          | 38 ++++++++
>   libsepol/src/kernel_to_cil.c                  |  1 -
>   libsepol/src/kernel_to_conf.c                 |  1 -
>   libsepol/src/mls.c                            |  3 +-
>   libsepol/src/policydb.c                       | 70 +++++++++++++-
>   libsepol/src/services.c                       | 87 ++++++++++-------
>   libsepol/src/sidtab.c                         |  2 +-
>   libsepol/src/write.c                          | 25 +++--
>   17 files changed, 196 insertions(+), 165 deletions(-)
>   delete mode 100644 libsepol/include/sepol/policydb/flask.h
>   create mode 100644 libsepol/src/flask.h
> 
> diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c
> index c9efaf8b442b..ba7a911b14df 100644
> --- a/checkpolicy/checkmodule.c
> +++ b/checkpolicy/checkmodule.c
> @@ -25,7 +25,6 @@
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/hierarchy.h>
>   #include <sepol/policydb/expand.h>
>   #include <sepol/policydb/link.h>
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index 7c5b63f82212..ed1516a6aa6a 100644
> --- a/checkpolicy/checkpolicy.c
> +++ b/checkpolicy/checkpolicy.c
> @@ -85,7 +85,6 @@
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
>   #include <sepol/policydb/hierarchy.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/expand.h>
>   #include <sepol/policydb/link.h>
>   
> diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
> index e295bc523258..c6733fa469c5 100644
> --- a/checkpolicy/policy_define.c
> +++ b/checkpolicy/policy_define.c
> @@ -53,7 +53,6 @@
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/hierarchy.h>
>   #include <sepol/policydb/polcaps.h>
>   #include "queue.h"
> @@ -5509,7 +5508,9 @@ int define_genfs_context_helper(char *fstype, int has_type)
>   {
>   	struct genfs *genfs_p, *genfs, *newgenfs;
>   	ocontext_t *newc, *c, *head, *p;
> +	class_datum_t *cladatum;
>   	char *type = NULL;
> +	const char *sclass;
>   	int len, len2;
>   
>   	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
> @@ -5571,30 +5572,39 @@ int define_genfs_context_helper(char *fstype, int has_type)
>   		}
>   		switch (type[0]) {
>   		case 'b':
> -			newc->v.sclass = SECCLASS_BLK_FILE;
> +			sclass = "blk_file";
>   			break;
>   		case 'c':
> -			newc->v.sclass = SECCLASS_CHR_FILE;
> +			sclass = "chr_file";
>   			break;
>   		case 'd':
> -			newc->v.sclass = SECCLASS_DIR;
> +			sclass = "dir";
>   			break;
>   		case 'p':
> -			newc->v.sclass = SECCLASS_FIFO_FILE;
> +			sclass = "fifo_file";
>   			break;
>   		case 'l':
> -			newc->v.sclass = SECCLASS_LNK_FILE;
> +			sclass = "lnk_file";
>   			break;
>   		case 's':
> -			newc->v.sclass = SECCLASS_SOCK_FILE;
> +			sclass = "sock_file";
>   			break;
>   		case '-':
> -			newc->v.sclass = SECCLASS_FILE;
> +			sclass = "file";
>   			break;
>   		default:
>   			yyerror2("invalid type %s", type);
>   			goto fail;
>   		}
> +
> +		cladatum = hashtab_search(policydbp->p_classes.table,
> +					  sclass);
> +		if (!cladatum) {
> +			yyerror2("could not find class %s for "
> +				 "genfscon statement", sclass);
> +			goto fail;
> +		}
> +		newc->v.sclass = cladatum->s.value;
>   	}
>   	if (parse_security_context(&newc->context[0]))
>   		goto fail;
> diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
> index abb7d88557e4..6098eb504d0c 100644
> --- a/checkpolicy/policy_parse.y
> +++ b/checkpolicy/policy_parse.y
> @@ -46,7 +46,6 @@
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/hierarchy.h>
>   #include <sepol/policydb/polcaps.h>
>   #include "queue.h"
> diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
> index 996cf33fff0e..8d6be2ff9522 100644
> --- a/checkpolicy/test/dismod.c
> +++ b/checkpolicy/test/dismod.c
> @@ -30,7 +30,6 @@
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/link.h>
>   #include <sepol/policydb/module.h>
>   #include <sepol/policydb/util.h>
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index 4cf6f481fe76..f8e20d32f9f1 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -42,7 +42,6 @@
>   #include <sepol/policydb/polcaps.h>
>   #include <sepol/policydb/conditional.h>
>   #include <sepol/policydb/constraint.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/expand.h>
>   #include <sepol/policydb/hierarchy.h>
>   
> diff --git a/libsepol/include/sepol/policydb/flask.h b/libsepol/include/sepol/policydb/flask.h
> deleted file mode 100644
> index 3134284b579f..000000000000
> --- a/libsepol/include/sepol/policydb/flask.h
> +++ /dev/null
> @@ -1,94 +0,0 @@
> -/* This file is automatically generated.  Do not edit. */
> -#ifndef _SEPOL_POLICYDB_FLASK_H_
> -#define _SEPOL_POLICYDB_FLASK_H_
> -
> -/*
> - * Security object class definitions
> - */
> -#define SECCLASS_SECURITY                                1
> -#define SECCLASS_PROCESS                                 2
> -#define SECCLASS_SYSTEM                                  3
> -#define SECCLASS_CAPABILITY                              4
> -#define SECCLASS_FILESYSTEM                              5
> -#define SECCLASS_FILE                                    6
> -#define SECCLASS_DIR                                     7
> -#define SECCLASS_FD                                      8
> -#define SECCLASS_LNK_FILE                                9
> -#define SECCLASS_CHR_FILE                                10
> -#define SECCLASS_BLK_FILE                                11
> -#define SECCLASS_SOCK_FILE                               12
> -#define SECCLASS_FIFO_FILE                               13
> -#define SECCLASS_SOCKET                                  14
> -#define SECCLASS_TCP_SOCKET                              15
> -#define SECCLASS_UDP_SOCKET                              16
> -#define SECCLASS_RAWIP_SOCKET                            17
> -#define SECCLASS_NODE                                    18
> -#define SECCLASS_NETIF                                   19
> -#define SECCLASS_NETLINK_SOCKET                          20
> -#define SECCLASS_PACKET_SOCKET                           21
> -#define SECCLASS_KEY_SOCKET                              22
> -#define SECCLASS_UNIX_STREAM_SOCKET                      23
> -#define SECCLASS_UNIX_DGRAM_SOCKET                       24
> -#define SECCLASS_SEM                                     25
> -#define SECCLASS_MSG                                     26
> -#define SECCLASS_MSGQ                                    27
> -#define SECCLASS_SHM                                     28
> -#define SECCLASS_IPC                                     29
> -#define SECCLASS_PASSWD                                  30
> -#define SECCLASS_DRAWABLE                                31
> -#define SECCLASS_WINDOW                                  32
> -#define SECCLASS_GC                                      33
> -#define SECCLASS_FONT                                    34
> -#define SECCLASS_COLORMAP                                35
> -#define SECCLASS_PROPERTY                                36
> -#define SECCLASS_CURSOR                                  37
> -#define SECCLASS_XCLIENT                                 38
> -#define SECCLASS_XINPUT                                  39
> -#define SECCLASS_XSERVER                                 40
> -#define SECCLASS_XEXTENSION                              41
> -#define SECCLASS_PAX                                     42
> -#define SECCLASS_NETLINK_ROUTE_SOCKET                    43
> -#define SECCLASS_NETLINK_FIREWALL_SOCKET                 44
> -#define SECCLASS_NETLINK_TCPDIAG_SOCKET                  45
> -#define SECCLASS_NETLINK_NFLOG_SOCKET                    46
> -#define SECCLASS_NETLINK_XFRM_SOCKET                     47
> -#define SECCLASS_NETLINK_SELINUX_SOCKET                  48
> -#define SECCLASS_NETLINK_AUDIT_SOCKET                    49
> -#define SECCLASS_NETLINK_IP6FW_SOCKET                    50
> -#define SECCLASS_NETLINK_DNRT_SOCKET                     51
> -#define SECCLASS_DBUS                                    52
> -
> -/*
> - * Security identifier indices for initial entities
> - */
> -#define SECINITSID_KERNEL                               1
> -#define SECINITSID_SECURITY                             2
> -#define SECINITSID_UNLABELED                            3
> -#define SECINITSID_FS                                   4
> -#define SECINITSID_FILE                                 5
> -#define SECINITSID_FILE_LABELS                          6
> -#define SECINITSID_INIT                                 7
> -#define SECINITSID_ANY_SOCKET                           8
> -#define SECINITSID_PORT                                 9
> -#define SECINITSID_NETIF                                10
> -#define SECINITSID_NETMSG                               11
> -#define SECINITSID_NODE                                 12
> -#define SECINITSID_IGMP_PACKET                          13
> -#define SECINITSID_ICMP_SOCKET                          14
> -#define SECINITSID_TCP_SOCKET                           15
> -#define SECINITSID_SYSCTL_MODPROBE                      16
> -#define SECINITSID_SYSCTL                               17
> -#define SECINITSID_SYSCTL_FS                            18
> -#define SECINITSID_SYSCTL_KERNEL                        19
> -#define SECINITSID_SYSCTL_NET                           20
> -#define SECINITSID_SYSCTL_NET_UNIX                      21
> -#define SECINITSID_SYSCTL_VM                            22
> -#define SECINITSID_SYSCTL_DEV                           23
> -#define SECINITSID_KMOD                                 24
> -#define SECINITSID_POLICY                               25
> -#define SECINITSID_SCMP_PACKET                          26
> -#define SECINITSID_DEVNULL                              27
> -
> -#define SECINITSID_NUM                                  27
> -
> -#endif
> diff --git a/libsepol/include/sepol/policydb/flask_types.h b/libsepol/include/sepol/policydb/flask_types.h
> index 714176fd2a44..a2f7c0bff3ba 100644
> --- a/libsepol/include/sepol/policydb/flask_types.h
> +++ b/libsepol/include/sepol/policydb/flask_types.h
> @@ -41,9 +41,7 @@ typedef uint32_t sepol_access_vector_t;
>   
>   /*
>    * Each object class is identified by a fixed-size value.
> - * The set of security classes is specified in flask/security_classes,
> - * with the corresponding constants defined in the automatically
> - * generated header file flask.h.
> + * The set of security classes is specified in policy.
>    */
>   typedef uint16_t sepol_security_class_t;
>   #define SEPOL_SECCLASS_NULL			0x0000	/* no class */
> diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
> index b0d2fdfc43f8..81b63fefbb20 100644
> --- a/libsepol/include/sepol/policydb/policydb.h
> +++ b/libsepol/include/sepol/policydb/policydb.h
> @@ -605,6 +605,11 @@ typedef struct policydb {
>   	unsigned policyvers;
>   
>   	unsigned handle_unknown;
> +
> +	sepol_security_class_t process_class;
> +	sepol_security_class_t dir_class;
> +	sepol_access_vector_t process_trans;
> +	sepol_access_vector_t process_trans_dyntrans;
>   } policydb_t;
>   
>   struct sepol_policydb {
> diff --git a/libsepol/src/flask.h b/libsepol/src/flask.h
> new file mode 100644
> index 000000000000..b4130bbcf544
> --- /dev/null
> +++ b/libsepol/src/flask.h
> @@ -0,0 +1,38 @@
> +/* This file is automatically generated.  Do not edit. */
> +#ifndef _SEPOL_POLICYDB_FLASK_H_
> +#define _SEPOL_POLICYDB_FLASK_H_
> +
> +/*
> + * Security identifier indices for initial entities
> + */
> +#define SECINITSID_KERNEL                               1
> +#define SECINITSID_SECURITY                             2
> +#define SECINITSID_UNLABELED                            3
> +#define SECINITSID_FS                                   4
> +#define SECINITSID_FILE                                 5
> +#define SECINITSID_FILE_LABELS                          6
> +#define SECINITSID_INIT                                 7
> +#define SECINITSID_ANY_SOCKET                           8
> +#define SECINITSID_PORT                                 9
> +#define SECINITSID_NETIF                                10
> +#define SECINITSID_NETMSG                               11
> +#define SECINITSID_NODE                                 12
> +#define SECINITSID_IGMP_PACKET                          13
> +#define SECINITSID_ICMP_SOCKET                          14
> +#define SECINITSID_TCP_SOCKET                           15
> +#define SECINITSID_SYSCTL_MODPROBE                      16
> +#define SECINITSID_SYSCTL                               17
> +#define SECINITSID_SYSCTL_FS                            18
> +#define SECINITSID_SYSCTL_KERNEL                        19
> +#define SECINITSID_SYSCTL_NET                           20
> +#define SECINITSID_SYSCTL_NET_UNIX                      21
> +#define SECINITSID_SYSCTL_VM                            22
> +#define SECINITSID_SYSCTL_DEV                           23
> +#define SECINITSID_KMOD                                 24
> +#define SECINITSID_POLICY                               25
> +#define SECINITSID_SCMP_PACKET                          26
> +#define SECINITSID_DEVNULL                              27
> +
> +#define SECINITSID_NUM                                  27
> +
> +#endif
> diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
> index ca2e4a9b265b..108767573e28 100644
> --- a/libsepol/src/kernel_to_cil.c
> +++ b/libsepol/src/kernel_to_cil.c
> @@ -18,7 +18,6 @@
>   
>   #include <sepol/policydb/avtab.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/hashtab.h>
>   #include <sepol/policydb/polcaps.h>
>   #include <sepol/policydb/policydb.h>
> diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
> index b49661625e03..1c7b7d226e9e 100644
> --- a/libsepol/src/kernel_to_conf.c
> +++ b/libsepol/src/kernel_to_conf.c
> @@ -17,7 +17,6 @@
>   
>   #include <sepol/policydb/avtab.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/hashtab.h>
>   #include <sepol/policydb/polcaps.h>
>   #include <sepol/policydb/policydb.h>
> diff --git a/libsepol/src/mls.c b/libsepol/src/mls.c
> index 6ff9a8468879..1ee90cf8dee1 100644
> --- a/libsepol/src/mls.c
> +++ b/libsepol/src/mls.c
> @@ -29,7 +29,6 @@
>   
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/services.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/context.h>
>   
>   #include <stdlib.h>
> @@ -649,7 +648,7 @@ int mls_compute_sid(policydb_t * policydb,
>   
>   		/* Fallthrough */
>   	case AVTAB_CHANGE:
> -		if (tclass == SECCLASS_PROCESS)
> +		if (tclass == policydb->process_class)
>   			/* Use the process MLS attributes. */
>   			return mls_copy_context(newcontext, scontext);
>   		else
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 67037b6d7760..ccc4b34c15d4 100644
> --- a/libsepol/src/policydb.c
> +++ b/libsepol/src/policydb.c
> @@ -49,7 +49,6 @@
>   #include <sepol/policydb/conditional.h>
>   #include <sepol/policydb/avrule_block.h>
>   #include <sepol/policydb/util.h>
> -#include <sepol/policydb/flask.h>
>   
>   #include "kernel_to_common.h"
>   #include "private.h"
> @@ -2562,7 +2561,7 @@ int role_trans_read(policydb_t *p, struct policy_file *fp)
>   				return -1;
>   			tr->tclass = le32_to_cpu(buf[0]);
>   		} else
> -			tr->tclass = SECCLASS_PROCESS;
> +			tr->tclass = p->process_class;
>   		ltr = tr;
>   	}
>   	return 0;
> @@ -3457,7 +3456,7 @@ static int range_read(policydb_t * p, struct policy_file *fp)
>   				goto err;
>   			rt->target_class = le32_to_cpu(buf[0]);
>   		} else
> -			rt->target_class = SECCLASS_PROCESS;
> +			rt->target_class = p->process_class;
>   		r = calloc(1, sizeof(*r));
>   		if (!r)
>   			goto err;
> @@ -3586,7 +3585,7 @@ static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r,
>   			if (ebitmap_read(&tr->classes, fp))
>   				return -1;
>   		} else {
> -			if (ebitmap_set_bit(&tr->classes, SECCLASS_PROCESS - 1, 1))
> +			if (ebitmap_set_bit(&tr->classes, p->process_class - 1, 1))
>   				return -1;
>   		}
>   
> @@ -3963,6 +3962,51 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
>   	return -1;
>   }
>   
> +static sepol_security_class_t policydb_string_to_security_class(
> +	struct policydb *policydb,
> +	const char *class_name)
> +{
> +	class_datum_t *tclass_datum;
> +
> +	tclass_datum = hashtab_search(policydb->p_classes.table,
> +				      (hashtab_key_t) class_name);
> +	if (!tclass_datum)
> +		return 0;
> +	return tclass_datum->s.value;
> +}
> +
> +static sepol_access_vector_t policydb_string_to_av_perm(
> +	struct policydb *policydb,
> +	sepol_security_class_t tclass,
> +	const char *perm_name)
> +{
> +	class_datum_t *tclass_datum;
> +	perm_datum_t *perm_datum;
> +
> +	if (!tclass || tclass > policydb->p_classes.nprim)
> +		return 0;
> +	tclass_datum = policydb->class_val_to_struct[tclass - 1];
> +
> +	perm_datum = (perm_datum_t *)
> +			hashtab_search(tclass_datum->permissions.table,
> +			(hashtab_key_t)perm_name);
> +	if (perm_datum != NULL)
> +		return 0x1U << (perm_datum->s.value - 1);
> +
> +	if (tclass_datum->comdatum == NULL)
> +		return 0;
> +
> +	perm_datum = (perm_datum_t *)
> +			hashtab_search(tclass_datum->comdatum->permissions.table,
> +			(hashtab_key_t)perm_name);
> +
> +	if (perm_datum != NULL)
> +		return 0x1U << (perm_datum->s.value - 1);
> +
> +	return 0;
> +}
> +
> +
>   /*
>    * Read the configuration data from a policy database binary
>    * representation file into a policy database structure.
> @@ -4190,6 +4234,14 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
>   		p->symtab[i].nprim = nprim;
>   	}
>   
> +	p->process_class = policydb_string_to_security_class(p, "process");
> +	if (!p->process_class)
> +		goto bad;
> +
> +	p->dir_class = policydb_string_to_security_class(p, "dir");
> +	if (!p->dir_class)
> +		goto bad;
> +
>   	if (policy_type == POLICY_KERN) {
>   		if (avtab_read(&p->te_avtab, fp, r_policyvers))
>   			goto bad;
> @@ -4233,6 +4285,16 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
>   	if (policydb_index_classes(p))
>   		goto bad;
>   
> +	p->process_trans = policydb_string_to_av_perm(p, p->process_class,
> +						      "transition");
> +	if (!p->process_trans)
> +		goto bad;
> +	p->process_trans_dyntrans = p->process_trans |
> +		policydb_string_to_av_perm(p, p->process_class,
> +					   "dyntransition");
> +	if (!p->process_trans_dyntrans)
> +		goto bad;
> +
>   	if (policydb_index_others(fp->handle, p, verbose))
>   		goto bad;
>   
> diff --git a/libsepol/src/services.c b/libsepol/src/services.c
> index 3758436f8e34..9dbba5673dfc 100644
> --- a/libsepol/src/services.c
> +++ b/libsepol/src/services.c
> @@ -1,4 +1,3 @@
> -
>   /*
>    * Author : Stephen Smalley, <sds@tycho.nsa.gov>
>    */
> @@ -59,7 +58,6 @@
>   #include <sepol/policydb/sidtab.h>
>   #include <sepol/policydb/services.h>
>   #include <sepol/policydb/conditional.h>
> -#include <sepol/policydb/flask.h>
>   #include <sepol/policydb/util.h>
>   
>   #include "debug.h"
> @@ -68,6 +66,7 @@
>   #include "av_permissions.h"
>   #include "dso.h"
>   #include "mls.h"
> +#include "flask.h"
>   
>   #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
>   #define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
> @@ -989,8 +988,8 @@ static int context_struct_compute_av(context_struct_t * scontext,
>   	 * role is changing, then check the (current_role, new_role)
>   	 * pair.
>   	 */
> -	if (tclass == SECCLASS_PROCESS &&
> -	    (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
> +	if (tclass == policydb->process_class &&
> +	    (avd->allowed & policydb->process_trans_dyntrans) &&
>   	    scontext->role != tcontext->role) {
>   		for (ra = policydb->role_allow; ra; ra = ra->next) {
>   			if (scontext->role == ra->role &&
> @@ -998,8 +997,7 @@ static int context_struct_compute_av(context_struct_t * scontext,
>   				break;
>   		}
>   		if (!ra)
> -			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
> -							  PROCESS__DYNTRANSITION);
> +			avd->allowed &= ~policydb->process_trans_dyntrans;
>   	}
>   
>   	if (requested & ~avd->allowed) {
> @@ -1361,6 +1359,7 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
>   			     sepol_security_class_t tclass,
>   			     uint32_t specified, sepol_security_id_t * out_sid)
>   {
> +	struct class_datum *cladatum = NULL;
>   	context_struct_t *scontext = 0, *tcontext = 0, newcontext;
>   	struct role_trans *roletr = 0;
>   	avtab_key_t avkey;
> @@ -1381,14 +1380,22 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
>   		goto out;
>   	}
>   
> +	if (tclass && tclass <= policydb->p_classes.nprim)
> +		cladatum = policydb->class_val_to_struct[tclass - 1];
> +
>   	context_init(&newcontext);
>   
>   	/* Set the user identity. */
>   	switch (specified) {
>   	case AVTAB_TRANSITION:
>   	case AVTAB_CHANGE:
> -		/* Use the process user identity. */
> -		newcontext.user = scontext->user;
> +		if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
> +			newcontext.user = tcontext->user;
> +		} else {
> +			/* notice this gets both DEFAULT_SOURCE and unset */
> +			/* Use the process user identity. */
> +			newcontext.user = scontext->user;
> +		}
>   		break;
>   	case AVTAB_MEMBER:
>   		/* Use the related object owner. */
> @@ -1396,18 +1403,31 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
>   		break;
>   	}
>   
> -	/* Set the role and type to default values. */
> -	switch (tclass) {
> -	case SECCLASS_PROCESS:
> -		/* Use the current role and type of process. */
> +	/* Set the role to default values. */
> +	if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
>   		newcontext.role = scontext->role;
> +	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
> +		newcontext.role = tcontext->role;
> +	} else {
> +		if (tclass == policydb->process_class)
> +			newcontext.role = scontext->role;
> +		else
> +			newcontext.role = OBJECT_R_VAL;
> +	}
> +
> +	/* Set the type to default values. */
> +	if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
>   		newcontext.type = scontext->type;
> -		break;
> -	default:
> -		/* Use the well-defined object role. */
> -		newcontext.role = OBJECT_R_VAL;
> -		/* Use the type of the related object. */
> +	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
>   		newcontext.type = tcontext->type;
> +	} else {
> +		if (tclass == policydb->process_class) {
> +			/* Use the type of process. */
> +			newcontext.type = scontext->type;
> +		} else {
> +			/* Use the type of the related object. */
> +			newcontext.type = tcontext->type;
> +		}
>   	}
>   
>   	/* Look for a type transition/member/change rule. */
> @@ -1435,23 +1455,18 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
>   	}
>   
>   	/* Check for class-specific changes. */
> -	switch (tclass) {
> -	case SECCLASS_PROCESS:
> -		if (specified & AVTAB_TRANSITION) {
> -			/* Look for a role transition rule. */
> -			for (roletr = policydb->role_tr; roletr;
> -			     roletr = roletr->next) {
> -				if (roletr->role == scontext->role &&
> -				    roletr->type == tcontext->type) {
> -					/* Use the role transition rule. */
> -					newcontext.role = roletr->new_role;
> -					break;
> -				}
> +	if (specified & AVTAB_TRANSITION) {
> +		/* Look for a role transition rule. */
> +		for (roletr = policydb->role_tr; roletr;
> +		     roletr = roletr->next) {
> +			if (roletr->role == scontext->role &&
> +			    roletr->type == tcontext->type &&
> +			    roletr->tclass == tclass) {
> +				/* Use the role transition rule. */
> +				newcontext.role = roletr->new_role;
> +				break;
>   			}
>   		}
> -		break;
> -	default:
> -		break;
>   	}
>   
>   	/* Set the MLS attributes.
> @@ -2203,10 +2218,10 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
>   				continue;
>   
>   			rc = context_struct_compute_av(fromcon, &usercon,
> -						       SECCLASS_PROCESS,
> -						       PROCESS__TRANSITION,
> +						       policydb->process_class,
> +						       policydb->process_trans,
>   						       &avd, &reason, NULL, 0);
> -			if (rc || !(avd.allowed & PROCESS__TRANSITION))
> +			if (rc || !(avd.allowed & policydb->process_trans))
>   				continue;
>   			rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
>   							 &sid);
> @@ -2321,7 +2336,7 @@ int hidden sepol_fs_use(const char *fstype,
>   		}
>   		*sid = c->sid[0];
>   	} else {
> -		rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
> +		rc = sepol_genfs_sid(fstype, "/", policydb->dir_class, sid);
>   		if (rc) {
>   			*behavior = SECURITY_FS_USE_NONE;
>   			rc = 0;
> diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c
> index 23b2e8f33630..e6bf57161e52 100644
> --- a/libsepol/src/sidtab.c
> +++ b/libsepol/src/sidtab.c
> @@ -14,7 +14,7 @@
>   
>   #include <sepol/policydb/sidtab.h>
>   
> -#include <sepol/policydb/flask.h>
> +#include "flask.h"
>   
>   #define SIDTAB_HASH(sid) \
>   (sid & SIDTAB_HASH_MASK)
> diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> index c6be2be2562e..ab5bc25889d4 100644
> --- a/libsepol/src/write.c
> +++ b/libsepol/src/write.c
> @@ -40,7 +40,6 @@
>   #include <sepol/policydb/policydb.h>
>   #include <sepol/policydb/conditional.h>
>   #include <sepol/policydb/expand.h>
> -#include <sepol/policydb/flask.h>
>   
>   #include "debug.h"
>   #include "private.h"
> @@ -514,7 +513,7 @@ static int role_trans_write(policydb_t *p, struct policy_file *fp)
>   
>   	nel = 0;
>   	for (tr = r; tr; tr = tr->next)
> -		if(new_roletr || tr->tclass == SECCLASS_PROCESS)
> +		if(new_roletr || tr->tclass == p->process_class)
>   			nel++;
>   
>   	buf[0] = cpu_to_le32(nel);
> @@ -522,7 +521,7 @@ static int role_trans_write(policydb_t *p, struct policy_file *fp)
>   	if (items != 1)
>   		return POLICYDB_ERROR;
>   	for (tr = r; tr; tr = tr->next) {
> -		if (!new_roletr && tr->tclass != SECCLASS_PROCESS) {
> +		if (!new_roletr && tr->tclass != p->process_class) {
>   			if (!warning_issued)
>   				WARN(fp->handle, "Discarding role_transition "
>   				     "rules for security classes other than "
> @@ -1574,6 +1573,7 @@ struct rangetrans_write_args {
>   	size_t nel;
>   	int new_rangetr;
>   	struct policy_file *fp;
> +	struct policydb *p;
>   };
>   
>   static int rangetrans_count(hashtab_key_t key,
> @@ -1582,11 +1582,12 @@ static int rangetrans_count(hashtab_key_t key,
>   {
>   	struct range_trans *rt = (struct range_trans *)key;
>   	struct rangetrans_write_args *args = ptr;
> +	struct policydb *p = args->p;
>   
>   	/* all range_transitions are written for the new format, only
>   	   process related range_transitions are written for the old
>   	   format, so count accordingly */
> -	if (args->new_rangetr || rt->target_class == SECCLASS_PROCESS)
> +	if (args->new_rangetr || rt->target_class == p->process_class)
>   		args->nel++;
>   	return 0;
>   }
> @@ -1598,12 +1599,13 @@ static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
>   	struct mls_range *r = data;
>   	struct rangetrans_write_args *args = ptr;
>   	struct policy_file *fp = args->fp;
> +	struct policydb *p = args->p;
>   	int new_rangetr = args->new_rangetr;
>   	size_t items;
>   	static int warning_issued = 0;
>   	int rc;
>   
> -	if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
> +	if (!new_rangetr && rt->target_class != p->process_class) {
>   		if (!warning_issued)
>   			WARN(fp->handle, "Discarding range_transition "
>   			     "rules for security classes other than "
> @@ -1642,6 +1644,7 @@ static int range_write(policydb_t * p, struct policy_file *fp)
>   	args.nel = 0;
>   	args.new_rangetr = new_rangetr;
>   	args.fp = fp;
> +	args.p = p;
>   	rc = hashtab_map(p->range_tr, rangetrans_count, &args);
>   	if (rc)
>   		return rc;
> @@ -1766,13 +1769,15 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
>   	return POLICYDB_SUCCESS;
>   }
>   
> -static int only_process(ebitmap_t *in)
> +static int only_process(ebitmap_t *in, struct policydb *p)
>   {
> -	unsigned int i;
> +	unsigned int i, value;
>   	ebitmap_node_t *node;
>   
> +	value = p->process_class - 1;
> +
>   	ebitmap_for_each_positive_bit(in, node, i) {
> -		if (i != SECCLASS_PROCESS - 1)
> +		if (i != value)
>   			return 0;
>   	}
>   	return 1;
> @@ -1789,7 +1794,7 @@ static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
>   	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
>   
>   	for (tr = t; tr; tr = tr->next)
> -		if (new_role || only_process(&tr->classes))
> +		if (new_role || only_process(&tr->classes, p))
>   			nel++;
>   
>   	buf[0] = cpu_to_le32(nel);
> @@ -1797,7 +1802,7 @@ static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
>   	if (items != 1)
>   		return POLICYDB_ERROR;
>   	for (tr = t; tr; tr = tr->next) {
> -		if (!new_role && !only_process(&tr->classes)) {
> +		if (!new_role && !only_process(&tr->classes, p)) {
>   			if (!warned)
>   				WARN(fp->handle, "Discarding role_transition "
>   					"rules for security classes other than "
>
Stephen Smalley Jan. 16, 2020, 8:36 p.m. UTC | #2
On 1/16/20 3:34 PM, Stephen Smalley wrote:
> On 1/16/20 3:01 PM, Stephen Smalley wrote:
>> libsepol carried its own (outdated) copy of flask.h with the generated
>> security class and initial SID values for use by the policy
>> compiler and the forked copy of the security server code
>> leveraged by tools such as audit2why.  Convert libsepol and
>> checkpolicy entirely to looking up class values from the policy,
>> remove the SECCLASS_* definitions from its flask.h header, and move
>> the header with its remaining initial SID definitions private to
>> libsepol.  While we are here, fix the sepol_compute_sid() logic to
>> properly support features long since added to the policy and kernel,
>> although there are no users of it other than checkpolicy -d (debug)
>> and it is not exported to users of the shared library.  There
>> are still some residual differences between the kernel logic and
>> libsepol.
>>
>> Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
> 
> I see that this fails travis-ci; looks like the problem is that it 
> trades using hardcoded values for SECCLASS_PROCESS and _DIR and the 
> PROCESS__TRANSITION/DYNTRANSITION permissions for requiring the strings 
> to be present in the policy and that isn't true of some test policies. 
> The kernel does require at least the process class and perms to be 
> present or it will reject the policy at load time presently (when it was 
> likewise converted long ago as part of dynamic class/perm support). 
> Options:
> - Weaken the restrictions in libsepol's policydb_read and accept the 
> fact that the class/perm values may be zero subsequently within libsepol.
> - Change the test policies to at least provide this minimal set.
> 
> The "dir" class isn't currently mapped at load time by the kernel but it 
> unmaps it for genfs_sid() matching so it still expects it to be present.

I guess if nothing else it ought to be conditional on 
SEPOL_TARGET_SELINUX to avoid breaking Xen policies.
diff mbox series

Patch

diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c
index c9efaf8b442b..ba7a911b14df 100644
--- a/checkpolicy/checkmodule.c
+++ b/checkpolicy/checkmodule.c
@@ -25,7 +25,6 @@ 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/hierarchy.h>
 #include <sepol/policydb/expand.h>
 #include <sepol/policydb/link.h>
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 7c5b63f82212..ed1516a6aa6a 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -85,7 +85,6 @@ 
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
 #include <sepol/policydb/hierarchy.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/expand.h>
 #include <sepol/policydb/link.h>
 
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index e295bc523258..c6733fa469c5 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -53,7 +53,6 @@ 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/hierarchy.h>
 #include <sepol/policydb/polcaps.h>
 #include "queue.h"
@@ -5509,7 +5508,9 @@  int define_genfs_context_helper(char *fstype, int has_type)
 {
 	struct genfs *genfs_p, *genfs, *newgenfs;
 	ocontext_t *newc, *c, *head, *p;
+	class_datum_t *cladatum;
 	char *type = NULL;
+	const char *sclass;
 	int len, len2;
 
 	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
@@ -5571,30 +5572,39 @@  int define_genfs_context_helper(char *fstype, int has_type)
 		}
 		switch (type[0]) {
 		case 'b':
-			newc->v.sclass = SECCLASS_BLK_FILE;
+			sclass = "blk_file";
 			break;
 		case 'c':
-			newc->v.sclass = SECCLASS_CHR_FILE;
+			sclass = "chr_file";
 			break;
 		case 'd':
-			newc->v.sclass = SECCLASS_DIR;
+			sclass = "dir";
 			break;
 		case 'p':
-			newc->v.sclass = SECCLASS_FIFO_FILE;
+			sclass = "fifo_file";
 			break;
 		case 'l':
-			newc->v.sclass = SECCLASS_LNK_FILE;
+			sclass = "lnk_file";
 			break;
 		case 's':
-			newc->v.sclass = SECCLASS_SOCK_FILE;
+			sclass = "sock_file";
 			break;
 		case '-':
-			newc->v.sclass = SECCLASS_FILE;
+			sclass = "file";
 			break;
 		default:
 			yyerror2("invalid type %s", type);
 			goto fail;
 		}
+
+		cladatum = hashtab_search(policydbp->p_classes.table,
+					  sclass);
+		if (!cladatum) {
+			yyerror2("could not find class %s for "
+				 "genfscon statement", sclass);
+			goto fail;
+		}
+		newc->v.sclass = cladatum->s.value;
 	}
 	if (parse_security_context(&newc->context[0]))
 		goto fail;
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index abb7d88557e4..6098eb504d0c 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -46,7 +46,6 @@ 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/hierarchy.h>
 #include <sepol/policydb/polcaps.h>
 #include "queue.h"
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index 996cf33fff0e..8d6be2ff9522 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -30,7 +30,6 @@ 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/link.h>
 #include <sepol/policydb/module.h>
 #include <sepol/policydb/util.h>
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 4cf6f481fe76..f8e20d32f9f1 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -42,7 +42,6 @@ 
 #include <sepol/policydb/polcaps.h>
 #include <sepol/policydb/conditional.h>
 #include <sepol/policydb/constraint.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/expand.h>
 #include <sepol/policydb/hierarchy.h>
 
diff --git a/libsepol/include/sepol/policydb/flask.h b/libsepol/include/sepol/policydb/flask.h
deleted file mode 100644
index 3134284b579f..000000000000
--- a/libsepol/include/sepol/policydb/flask.h
+++ /dev/null
@@ -1,94 +0,0 @@ 
-/* This file is automatically generated.  Do not edit. */
-#ifndef _SEPOL_POLICYDB_FLASK_H_
-#define _SEPOL_POLICYDB_FLASK_H_
-
-/*
- * Security object class definitions
- */
-#define SECCLASS_SECURITY                                1
-#define SECCLASS_PROCESS                                 2
-#define SECCLASS_SYSTEM                                  3
-#define SECCLASS_CAPABILITY                              4
-#define SECCLASS_FILESYSTEM                              5
-#define SECCLASS_FILE                                    6
-#define SECCLASS_DIR                                     7
-#define SECCLASS_FD                                      8
-#define SECCLASS_LNK_FILE                                9
-#define SECCLASS_CHR_FILE                                10
-#define SECCLASS_BLK_FILE                                11
-#define SECCLASS_SOCK_FILE                               12
-#define SECCLASS_FIFO_FILE                               13
-#define SECCLASS_SOCKET                                  14
-#define SECCLASS_TCP_SOCKET                              15
-#define SECCLASS_UDP_SOCKET                              16
-#define SECCLASS_RAWIP_SOCKET                            17
-#define SECCLASS_NODE                                    18
-#define SECCLASS_NETIF                                   19
-#define SECCLASS_NETLINK_SOCKET                          20
-#define SECCLASS_PACKET_SOCKET                           21
-#define SECCLASS_KEY_SOCKET                              22
-#define SECCLASS_UNIX_STREAM_SOCKET                      23
-#define SECCLASS_UNIX_DGRAM_SOCKET                       24
-#define SECCLASS_SEM                                     25
-#define SECCLASS_MSG                                     26
-#define SECCLASS_MSGQ                                    27
-#define SECCLASS_SHM                                     28
-#define SECCLASS_IPC                                     29
-#define SECCLASS_PASSWD                                  30
-#define SECCLASS_DRAWABLE                                31
-#define SECCLASS_WINDOW                                  32
-#define SECCLASS_GC                                      33
-#define SECCLASS_FONT                                    34
-#define SECCLASS_COLORMAP                                35
-#define SECCLASS_PROPERTY                                36
-#define SECCLASS_CURSOR                                  37
-#define SECCLASS_XCLIENT                                 38
-#define SECCLASS_XINPUT                                  39
-#define SECCLASS_XSERVER                                 40
-#define SECCLASS_XEXTENSION                              41
-#define SECCLASS_PAX                                     42
-#define SECCLASS_NETLINK_ROUTE_SOCKET                    43
-#define SECCLASS_NETLINK_FIREWALL_SOCKET                 44
-#define SECCLASS_NETLINK_TCPDIAG_SOCKET                  45
-#define SECCLASS_NETLINK_NFLOG_SOCKET                    46
-#define SECCLASS_NETLINK_XFRM_SOCKET                     47
-#define SECCLASS_NETLINK_SELINUX_SOCKET                  48
-#define SECCLASS_NETLINK_AUDIT_SOCKET                    49
-#define SECCLASS_NETLINK_IP6FW_SOCKET                    50
-#define SECCLASS_NETLINK_DNRT_SOCKET                     51
-#define SECCLASS_DBUS                                    52
-
-/*
- * Security identifier indices for initial entities
- */
-#define SECINITSID_KERNEL                               1
-#define SECINITSID_SECURITY                             2
-#define SECINITSID_UNLABELED                            3
-#define SECINITSID_FS                                   4
-#define SECINITSID_FILE                                 5
-#define SECINITSID_FILE_LABELS                          6
-#define SECINITSID_INIT                                 7
-#define SECINITSID_ANY_SOCKET                           8
-#define SECINITSID_PORT                                 9
-#define SECINITSID_NETIF                                10
-#define SECINITSID_NETMSG                               11
-#define SECINITSID_NODE                                 12
-#define SECINITSID_IGMP_PACKET                          13
-#define SECINITSID_ICMP_SOCKET                          14
-#define SECINITSID_TCP_SOCKET                           15
-#define SECINITSID_SYSCTL_MODPROBE                      16
-#define SECINITSID_SYSCTL                               17
-#define SECINITSID_SYSCTL_FS                            18
-#define SECINITSID_SYSCTL_KERNEL                        19
-#define SECINITSID_SYSCTL_NET                           20
-#define SECINITSID_SYSCTL_NET_UNIX                      21
-#define SECINITSID_SYSCTL_VM                            22
-#define SECINITSID_SYSCTL_DEV                           23
-#define SECINITSID_KMOD                                 24
-#define SECINITSID_POLICY                               25
-#define SECINITSID_SCMP_PACKET                          26
-#define SECINITSID_DEVNULL                              27
-
-#define SECINITSID_NUM                                  27
-
-#endif
diff --git a/libsepol/include/sepol/policydb/flask_types.h b/libsepol/include/sepol/policydb/flask_types.h
index 714176fd2a44..a2f7c0bff3ba 100644
--- a/libsepol/include/sepol/policydb/flask_types.h
+++ b/libsepol/include/sepol/policydb/flask_types.h
@@ -41,9 +41,7 @@  typedef uint32_t sepol_access_vector_t;
 
 /*
  * Each object class is identified by a fixed-size value.
- * The set of security classes is specified in flask/security_classes, 
- * with the corresponding constants defined in the automatically 
- * generated header file flask.h.
+ * The set of security classes is specified in policy.
  */
 typedef uint16_t sepol_security_class_t;
 #define SEPOL_SECCLASS_NULL			0x0000	/* no class */
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index b0d2fdfc43f8..81b63fefbb20 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -605,6 +605,11 @@  typedef struct policydb {
 	unsigned policyvers;
 
 	unsigned handle_unknown;
+
+	sepol_security_class_t process_class;
+	sepol_security_class_t dir_class;
+	sepol_access_vector_t process_trans;
+	sepol_access_vector_t process_trans_dyntrans;
 } policydb_t;
 
 struct sepol_policydb {
diff --git a/libsepol/src/flask.h b/libsepol/src/flask.h
new file mode 100644
index 000000000000..b4130bbcf544
--- /dev/null
+++ b/libsepol/src/flask.h
@@ -0,0 +1,38 @@ 
+/* This file is automatically generated.  Do not edit. */
+#ifndef _SEPOL_POLICYDB_FLASK_H_
+#define _SEPOL_POLICYDB_FLASK_H_
+
+/*
+ * Security identifier indices for initial entities
+ */
+#define SECINITSID_KERNEL                               1
+#define SECINITSID_SECURITY                             2
+#define SECINITSID_UNLABELED                            3
+#define SECINITSID_FS                                   4
+#define SECINITSID_FILE                                 5
+#define SECINITSID_FILE_LABELS                          6
+#define SECINITSID_INIT                                 7
+#define SECINITSID_ANY_SOCKET                           8
+#define SECINITSID_PORT                                 9
+#define SECINITSID_NETIF                                10
+#define SECINITSID_NETMSG                               11
+#define SECINITSID_NODE                                 12
+#define SECINITSID_IGMP_PACKET                          13
+#define SECINITSID_ICMP_SOCKET                          14
+#define SECINITSID_TCP_SOCKET                           15
+#define SECINITSID_SYSCTL_MODPROBE                      16
+#define SECINITSID_SYSCTL                               17
+#define SECINITSID_SYSCTL_FS                            18
+#define SECINITSID_SYSCTL_KERNEL                        19
+#define SECINITSID_SYSCTL_NET                           20
+#define SECINITSID_SYSCTL_NET_UNIX                      21
+#define SECINITSID_SYSCTL_VM                            22
+#define SECINITSID_SYSCTL_DEV                           23
+#define SECINITSID_KMOD                                 24
+#define SECINITSID_POLICY                               25
+#define SECINITSID_SCMP_PACKET                          26
+#define SECINITSID_DEVNULL                              27
+
+#define SECINITSID_NUM                                  27
+
+#endif
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index ca2e4a9b265b..108767573e28 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -18,7 +18,6 @@ 
 
 #include <sepol/policydb/avtab.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/hashtab.h>
 #include <sepol/policydb/polcaps.h>
 #include <sepol/policydb/policydb.h>
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index b49661625e03..1c7b7d226e9e 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -17,7 +17,6 @@ 
 
 #include <sepol/policydb/avtab.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/hashtab.h>
 #include <sepol/policydb/polcaps.h>
 #include <sepol/policydb/policydb.h>
diff --git a/libsepol/src/mls.c b/libsepol/src/mls.c
index 6ff9a8468879..1ee90cf8dee1 100644
--- a/libsepol/src/mls.c
+++ b/libsepol/src/mls.c
@@ -29,7 +29,6 @@ 
 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/services.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/context.h>
 
 #include <stdlib.h>
@@ -649,7 +648,7 @@  int mls_compute_sid(policydb_t * policydb,
 
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if (tclass == SECCLASS_PROCESS)
+		if (tclass == policydb->process_class)
 			/* Use the process MLS attributes. */
 			return mls_copy_context(newcontext, scontext);
 		else
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 67037b6d7760..ccc4b34c15d4 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -49,7 +49,6 @@ 
 #include <sepol/policydb/conditional.h>
 #include <sepol/policydb/avrule_block.h>
 #include <sepol/policydb/util.h>
-#include <sepol/policydb/flask.h>
 
 #include "kernel_to_common.h"
 #include "private.h"
@@ -2562,7 +2561,7 @@  int role_trans_read(policydb_t *p, struct policy_file *fp)
 				return -1;
 			tr->tclass = le32_to_cpu(buf[0]);
 		} else
-			tr->tclass = SECCLASS_PROCESS;
+			tr->tclass = p->process_class;
 		ltr = tr;
 	}
 	return 0;
@@ -3457,7 +3456,7 @@  static int range_read(policydb_t * p, struct policy_file *fp)
 				goto err;
 			rt->target_class = le32_to_cpu(buf[0]);
 		} else
-			rt->target_class = SECCLASS_PROCESS;
+			rt->target_class = p->process_class;
 		r = calloc(1, sizeof(*r));
 		if (!r)
 			goto err;
@@ -3586,7 +3585,7 @@  static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r,
 			if (ebitmap_read(&tr->classes, fp))
 				return -1;
 		} else {
-			if (ebitmap_set_bit(&tr->classes, SECCLASS_PROCESS - 1, 1))
+			if (ebitmap_set_bit(&tr->classes, p->process_class - 1, 1))
 				return -1;
 		}
 
@@ -3963,6 +3962,51 @@  static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
 	return -1;
 }
 
+static sepol_security_class_t policydb_string_to_security_class(
+	struct policydb *policydb,
+	const char *class_name)
+{
+	class_datum_t *tclass_datum;
+
+	tclass_datum = hashtab_search(policydb->p_classes.table,
+				      (hashtab_key_t) class_name);
+	if (!tclass_datum)
+		return 0;
+	return tclass_datum->s.value;
+}
+
+static sepol_access_vector_t policydb_string_to_av_perm(
+	struct policydb *policydb,
+	sepol_security_class_t tclass,
+	const char *perm_name)
+{
+	class_datum_t *tclass_datum;
+	perm_datum_t *perm_datum;
+
+	if (!tclass || tclass > policydb->p_classes.nprim)
+		return 0;
+	tclass_datum = policydb->class_val_to_struct[tclass - 1];
+
+	perm_datum = (perm_datum_t *)
+			hashtab_search(tclass_datum->permissions.table,
+			(hashtab_key_t)perm_name);
+	if (perm_datum != NULL)
+		return 0x1U << (perm_datum->s.value - 1);
+
+	if (tclass_datum->comdatum == NULL)
+		return 0;
+
+	perm_datum = (perm_datum_t *)
+			hashtab_search(tclass_datum->comdatum->permissions.table,
+			(hashtab_key_t)perm_name);
+
+	if (perm_datum != NULL)
+		return 0x1U << (perm_datum->s.value - 1);
+
+	return 0;
+}
+
+
 /*
  * Read the configuration data from a policy database binary
  * representation file into a policy database structure.
@@ -4190,6 +4234,14 @@  int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
 		p->symtab[i].nprim = nprim;
 	}
 
+	p->process_class = policydb_string_to_security_class(p, "process");
+	if (!p->process_class)
+		goto bad;
+
+	p->dir_class = policydb_string_to_security_class(p, "dir");
+	if (!p->dir_class)
+		goto bad;
+
 	if (policy_type == POLICY_KERN) {
 		if (avtab_read(&p->te_avtab, fp, r_policyvers))
 			goto bad;
@@ -4233,6 +4285,16 @@  int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
 	if (policydb_index_classes(p))
 		goto bad;
 
+	p->process_trans = policydb_string_to_av_perm(p, p->process_class,
+						      "transition");
+	if (!p->process_trans)
+		goto bad;
+	p->process_trans_dyntrans = p->process_trans |
+		policydb_string_to_av_perm(p, p->process_class,
+					   "dyntransition");
+	if (!p->process_trans_dyntrans)
+		goto bad;
+
 	if (policydb_index_others(fp->handle, p, verbose))
 		goto bad;
 
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 3758436f8e34..9dbba5673dfc 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1,4 +1,3 @@ 
-
 /*
  * Author : Stephen Smalley, <sds@tycho.nsa.gov>
  */
@@ -59,7 +58,6 @@ 
 #include <sepol/policydb/sidtab.h>
 #include <sepol/policydb/services.h>
 #include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
 #include <sepol/policydb/util.h>
 
 #include "debug.h"
@@ -68,6 +66,7 @@ 
 #include "av_permissions.h"
 #include "dso.h"
 #include "mls.h"
+#include "flask.h"
 
 #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
 #define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
@@ -989,8 +988,8 @@  static int context_struct_compute_av(context_struct_t * scontext,
 	 * role is changing, then check the (current_role, new_role) 
 	 * pair.
 	 */
-	if (tclass == SECCLASS_PROCESS &&
-	    (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
+	if (tclass == policydb->process_class &&
+	    (avd->allowed & policydb->process_trans_dyntrans) &&
 	    scontext->role != tcontext->role) {
 		for (ra = policydb->role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
@@ -998,8 +997,7 @@  static int context_struct_compute_av(context_struct_t * scontext,
 				break;
 		}
 		if (!ra)
-			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
-							  PROCESS__DYNTRANSITION);
+			avd->allowed &= ~policydb->process_trans_dyntrans;
 	}
 
 	if (requested & ~avd->allowed) {
@@ -1361,6 +1359,7 @@  static int sepol_compute_sid(sepol_security_id_t ssid,
 			     sepol_security_class_t tclass,
 			     uint32_t specified, sepol_security_id_t * out_sid)
 {
+	struct class_datum *cladatum = NULL;
 	context_struct_t *scontext = 0, *tcontext = 0, newcontext;
 	struct role_trans *roletr = 0;
 	avtab_key_t avkey;
@@ -1381,14 +1380,22 @@  static int sepol_compute_sid(sepol_security_id_t ssid,
 		goto out;
 	}
 
+	if (tclass && tclass <= policydb->p_classes.nprim)
+		cladatum = policydb->class_val_to_struct[tclass - 1];
+
 	context_init(&newcontext);
 
 	/* Set the user identity. */
 	switch (specified) {
 	case AVTAB_TRANSITION:
 	case AVTAB_CHANGE:
-		/* Use the process user identity. */
-		newcontext.user = scontext->user;
+		if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
+			newcontext.user = tcontext->user;
+		} else {
+			/* notice this gets both DEFAULT_SOURCE and unset */
+			/* Use the process user identity. */
+			newcontext.user = scontext->user;
+		}
 		break;
 	case AVTAB_MEMBER:
 		/* Use the related object owner. */
@@ -1396,18 +1403,31 @@  static int sepol_compute_sid(sepol_security_id_t ssid,
 		break;
 	}
 
-	/* Set the role and type to default values. */
-	switch (tclass) {
-	case SECCLASS_PROCESS:
-		/* Use the current role and type of process. */
+	/* Set the role to default values. */
+	if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
 		newcontext.role = scontext->role;
+	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
+		newcontext.role = tcontext->role;
+	} else {
+		if (tclass == policydb->process_class)
+			newcontext.role = scontext->role;
+		else
+			newcontext.role = OBJECT_R_VAL;
+	}
+
+	/* Set the type to default values. */
+	if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
 		newcontext.type = scontext->type;
-		break;
-	default:
-		/* Use the well-defined object role. */
-		newcontext.role = OBJECT_R_VAL;
-		/* Use the type of the related object. */
+	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
 		newcontext.type = tcontext->type;
+	} else {
+		if (tclass == policydb->process_class) {
+			/* Use the type of process. */
+			newcontext.type = scontext->type;
+		} else {
+			/* Use the type of the related object. */
+			newcontext.type = tcontext->type;
+		}
 	}
 
 	/* Look for a type transition/member/change rule. */
@@ -1435,23 +1455,18 @@  static int sepol_compute_sid(sepol_security_id_t ssid,
 	}
 
 	/* Check for class-specific changes. */
-	switch (tclass) {
-	case SECCLASS_PROCESS:
-		if (specified & AVTAB_TRANSITION) {
-			/* Look for a role transition rule. */
-			for (roletr = policydb->role_tr; roletr;
-			     roletr = roletr->next) {
-				if (roletr->role == scontext->role &&
-				    roletr->type == tcontext->type) {
-					/* Use the role transition rule. */
-					newcontext.role = roletr->new_role;
-					break;
-				}
+	if (specified & AVTAB_TRANSITION) {
+		/* Look for a role transition rule. */
+		for (roletr = policydb->role_tr; roletr;
+		     roletr = roletr->next) {
+			if (roletr->role == scontext->role &&
+			    roletr->type == tcontext->type &&
+			    roletr->tclass == tclass) {
+				/* Use the role transition rule. */
+				newcontext.role = roletr->new_role;
+				break;
 			}
 		}
-		break;
-	default:
-		break;
 	}
 
 	/* Set the MLS attributes.
@@ -2203,10 +2218,10 @@  int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
 				continue;
 
 			rc = context_struct_compute_av(fromcon, &usercon,
-						       SECCLASS_PROCESS,
-						       PROCESS__TRANSITION,
+						       policydb->process_class,
+						       policydb->process_trans,
 						       &avd, &reason, NULL, 0);
-			if (rc || !(avd.allowed & PROCESS__TRANSITION))
+			if (rc || !(avd.allowed & policydb->process_trans))
 				continue;
 			rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
 							 &sid);
@@ -2321,7 +2336,7 @@  int hidden sepol_fs_use(const char *fstype,
 		}
 		*sid = c->sid[0];
 	} else {
-		rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+		rc = sepol_genfs_sid(fstype, "/", policydb->dir_class, sid);
 		if (rc) {
 			*behavior = SECURITY_FS_USE_NONE;
 			rc = 0;
diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c
index 23b2e8f33630..e6bf57161e52 100644
--- a/libsepol/src/sidtab.c
+++ b/libsepol/src/sidtab.c
@@ -14,7 +14,7 @@ 
 
 #include <sepol/policydb/sidtab.h>
 
-#include <sepol/policydb/flask.h>
+#include "flask.h"
 
 #define SIDTAB_HASH(sid) \
 (sid & SIDTAB_HASH_MASK)
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index c6be2be2562e..ab5bc25889d4 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -40,7 +40,6 @@ 
 #include <sepol/policydb/policydb.h>
 #include <sepol/policydb/conditional.h>
 #include <sepol/policydb/expand.h>
-#include <sepol/policydb/flask.h>
 
 #include "debug.h"
 #include "private.h"
@@ -514,7 +513,7 @@  static int role_trans_write(policydb_t *p, struct policy_file *fp)
 
 	nel = 0;
 	for (tr = r; tr; tr = tr->next)
-		if(new_roletr || tr->tclass == SECCLASS_PROCESS)
+		if(new_roletr || tr->tclass == p->process_class)
 			nel++;
 
 	buf[0] = cpu_to_le32(nel);
@@ -522,7 +521,7 @@  static int role_trans_write(policydb_t *p, struct policy_file *fp)
 	if (items != 1)
 		return POLICYDB_ERROR;
 	for (tr = r; tr; tr = tr->next) {
-		if (!new_roletr && tr->tclass != SECCLASS_PROCESS) {
+		if (!new_roletr && tr->tclass != p->process_class) {
 			if (!warning_issued)
 				WARN(fp->handle, "Discarding role_transition "
 				     "rules for security classes other than "
@@ -1574,6 +1573,7 @@  struct rangetrans_write_args {
 	size_t nel;
 	int new_rangetr;
 	struct policy_file *fp;
+	struct policydb *p;
 };
 
 static int rangetrans_count(hashtab_key_t key,
@@ -1582,11 +1582,12 @@  static int rangetrans_count(hashtab_key_t key,
 {
 	struct range_trans *rt = (struct range_trans *)key;
 	struct rangetrans_write_args *args = ptr;
+	struct policydb *p = args->p;
 
 	/* all range_transitions are written for the new format, only
 	   process related range_transitions are written for the old
 	   format, so count accordingly */
-	if (args->new_rangetr || rt->target_class == SECCLASS_PROCESS)
+	if (args->new_rangetr || rt->target_class == p->process_class)
 		args->nel++;
 	return 0;
 }
@@ -1598,12 +1599,13 @@  static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
 	struct mls_range *r = data;
 	struct rangetrans_write_args *args = ptr;
 	struct policy_file *fp = args->fp;
+	struct policydb *p = args->p;
 	int new_rangetr = args->new_rangetr;
 	size_t items;
 	static int warning_issued = 0;
 	int rc;
 
-	if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
+	if (!new_rangetr && rt->target_class != p->process_class) {
 		if (!warning_issued)
 			WARN(fp->handle, "Discarding range_transition "
 			     "rules for security classes other than "
@@ -1642,6 +1644,7 @@  static int range_write(policydb_t * p, struct policy_file *fp)
 	args.nel = 0;
 	args.new_rangetr = new_rangetr;
 	args.fp = fp;
+	args.p = p;
 	rc = hashtab_map(p->range_tr, rangetrans_count, &args);
 	if (rc)
 		return rc;
@@ -1766,13 +1769,15 @@  static int avrule_write_list(policydb_t *p, avrule_t * avrules,
 	return POLICYDB_SUCCESS;
 }
 
-static int only_process(ebitmap_t *in)
+static int only_process(ebitmap_t *in, struct policydb *p)
 {
-	unsigned int i;
+	unsigned int i, value;
 	ebitmap_node_t *node;
 
+	value = p->process_class - 1;
+
 	ebitmap_for_each_positive_bit(in, node, i) {
-		if (i != SECCLASS_PROCESS - 1)
+		if (i != value)
 			return 0;
 	}
 	return 1;
@@ -1789,7 +1794,7 @@  static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
 
 	for (tr = t; tr; tr = tr->next)
-		if (new_role || only_process(&tr->classes))
+		if (new_role || only_process(&tr->classes, p))
 			nel++;
 
 	buf[0] = cpu_to_le32(nel);
@@ -1797,7 +1802,7 @@  static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
 	if (items != 1)
 		return POLICYDB_ERROR;
 	for (tr = t; tr; tr = tr->next) {
-		if (!new_role && !only_process(&tr->classes)) {
+		if (!new_role && !only_process(&tr->classes, p)) {
 			if (!warned)
 				WARN(fp->handle, "Discarding role_transition "
 					"rules for security classes other than "