On 2011-07-21 11:29, Kohei Kaigai wrote:
The attached patch is revised userspace-avc patch.

List of updates:
- The GUC of sepgsql.avc_threshold was removed.
- "char *ucontext" of avc_cache was replaced by "bool tcontext_is_valid".
- Comments added onto static variables
- Comments of sepgsql_avc_unlabeled() was revised.
- Comments of sepgsql_avc_compute() was simplified.
- Comments of sepgsql_avc_check_perms_label() also mention about
   permissive domain, that performs similar to system's permissive mode.
- selinux_status_close() become invoked on on_proc_exit() hook.
Thank you for the update, I'm looking at it right now and with a new look have some more questions. I took the liberty to supply a patch to be applied after your v5 uavc patch.

1) At a few call sites of sepgsql_avc_lookup, a null tcontext is detected, and then replaced by "unlabeled". I moved this to sepgsql_avc_lookup itself. 2) Also I thought if it could work to not remember tcontext is valid, but instead remember the consequence, which is that it is replaced by "unlabeled". It makes the avc_cache struct shorter and the code somewhat simpler.

regards,
--

Yeb Havinga
http://www.mgrid.net/
Mastering Medical Data

diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c
new file mode 100644
index 57a5197..2bcfedf
*** a/contrib/sepgsql/uavc.c
--- b/contrib/sepgsql/uavc.c
*************** typedef struct
*** 41,48 ****
  
  	bool		permissive;	/* true, if permissive rule */
  	bool		hot_cache;	/* true, if recently referenced */
- 	bool		tcontext_is_valid;
- 							/* true, if tcontext is valid */
  	char	   *ncontext;	/* temporary scontext on execution of trusted
  							 * procedure, or NULL elsewhere */
  } avc_cache;
--- 41,46 ----
*************** sepgsql_avc_reset(void)
*** 88,94 ****
  
  /*
   * Reclaim caches recently unreferenced
!  */	
  static void
  sepgsql_avc_reclaim(void)
  {
--- 86,92 ----
  
  /*
   * Reclaim caches recently unreferenced
!  */
  static void
  sepgsql_avc_reclaim(void)
  {
*************** sepgsql_avc_check_valid(void)
*** 153,159 ****
  /*
   * sepgsql_avc_unlabeled
   *
!  * It returns an alternative label to be applied when no label or invalid 
   * label would be assigned on objects.
   */
  static char *
--- 151,157 ----
  /*
   * sepgsql_avc_unlabeled
   *
!  * It returns an alternative label to be applied when no label or invalid
   * label would be assigned on objects.
   */
  static char *
*************** sepgsql_avc_unlabeled(void)
*** 184,198 ****
  }
  
  /*
!  * sepgsql_avc_compute 
   *
   * A fallback path, when cache mishit. It asks SELinux its access control
   * decision for the supplied pair of security context and object class.
   */
  static avc_cache *
! sepgsql_avc_compute(const char *scontext, const char *tcontext, uint16 tclass)
  {
- 	char		   *ucontext = NULL;
  	char		   *ncontext = NULL;
  	MemoryContext	oldctx;
  	avc_cache	   *cache;
--- 182,195 ----
  }
  
  /*
!  * sepgsql_avc_compute
   *
   * A fallback path, when cache mishit. It asks SELinux its access control
   * decision for the supplied pair of security context and object class.
   */
  static avc_cache *
! sepgsql_avc_compute(const char *scontext, char *tcontext, uint16 tclass)
  {
  	char		   *ncontext = NULL;
  	MemoryContext	oldctx;
  	avc_cache	   *cache;
*************** sepgsql_avc_compute(const char *scontext
*** 207,224 ****
  	 * Validation check of the supplied security context.
  	 * Because it always invoke system-call, frequent check should be avoided.
  	 * Unless security policy is reloaded, validation status shall be kept, so
! 	 * we also cache whether the supplied security context was valid, or not.
  	 */
  	if (security_check_context_raw((security_context_t)tcontext) != 0)
! 		ucontext = sepgsql_avc_unlabeled();
  
! 	/*
! 	 * Ask SELinux its access control decision
! 	 */
! 	if (!ucontext)
! 		sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
! 	else
! 		sepgsql_compute_avd(scontext, ucontext, tclass, &avd);
  
  	/*
  	 * To boost up trusted procedure checks on db_procedure object
--- 204,216 ----
  	 * Validation check of the supplied security context.
  	 * Because it always invoke system-call, frequent check should be avoided.
  	 * Unless security policy is reloaded, validation status shall be kept, so
! 	 * we also cache the invalid tcontext replaced by the unlabeled context.
  	 */
  	if (security_check_context_raw((security_context_t)tcontext) != 0)
! 		tcontext = sepgsql_avc_unlabeled();
  
! 	/* Ask SELinux its access control decision */
! 	sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
  
  	/*
  	 * To boost up trusted procedure checks on db_procedure object
*************** sepgsql_avc_compute(const char *scontext
*** 227,238 ****
  	 */
  	if (tclass == SEPG_CLASS_DB_PROCEDURE)
  	{
! 		if (!ucontext)
! 			ncontext = sepgsql_compute_create(scontext, tcontext,
! 											  SEPG_CLASS_PROCESS);
! 		else
! 			ncontext = sepgsql_compute_create(scontext, ucontext,
! 											  SEPG_CLASS_PROCESS);
  		if (strcmp(scontext, ncontext) == 0)
  		{
  			pfree(ncontext);
--- 219,227 ----
  	 */
  	if (tclass == SEPG_CLASS_DB_PROCEDURE)
  	{
! 		ncontext = sepgsql_compute_create(scontext, tcontext,
! 										  SEPG_CLASS_PROCESS);
! 
  		if (strcmp(scontext, ncontext) == 0)
  		{
  			pfree(ncontext);
*************** sepgsql_avc_compute(const char *scontext
*** 258,267 ****
  	cache->hot_cache = true;
  	if (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE)
  		cache->permissive = true;
! 	if (!ucontext)
! 		cache->tcontext_is_valid = true;
! 	if (ncontext)
! 		cache->ncontext = pstrdup(ncontext);
  
  	avc_num_caches++;
  
--- 247,253 ----
  	cache->hot_cache = true;
  	if (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE)
  		cache->permissive = true;
! 	cache->ncontext = ncontext;
  
  	avc_num_caches++;
  
*************** sepgsql_avc_compute(const char *scontext
*** 283,295 ****
   * a new cache entry.
   */
  static avc_cache *
! sepgsql_avc_lookup(const char *scontext, const char *tcontext, uint16 tclass)
  {
  	avc_cache  *cache;
  	ListCell   *cell;
  	uint32		hash;
  	int			index;
  
  	hash = sepgsql_avc_hash(scontext, tcontext, tclass);
  	index = hash % AVC_NUM_SLOTS;
  
--- 269,288 ----
   * a new cache entry.
   */
  static avc_cache *
! sepgsql_avc_lookup(const char *scontext, char *tcontext, uint16 tclass)
  {
  	avc_cache  *cache;
  	ListCell   *cell;
  	uint32		hash;
  	int			index;
  
+ 	/*
+ 	 * If target object is not labeled, we assume it has
+ 	 * system 'unlabeled' security context instead.
+ 	 */
+ 	if (!tcontext)
+ 		tcontext = sepgsql_avc_unlabeled();
+ 
  	hash = sepgsql_avc_hash(scontext, tcontext, tclass);
  	index = hash % AVC_NUM_SLOTS;
  
*************** sepgsql_avc_lookup(const char *scontext,
*** 303,313 ****
  			strcmp(cache->scontext, scontext) == 0)
  		{
  			cache->hot_cache = true;
  			return cache;
  		}
  	}
  	/* not found, so insert a new cache */
! 	return sepgsql_avc_compute(scontext, tcontext, tclass);
  }
  
  /*
--- 296,307 ----
  			strcmp(cache->scontext, scontext) == 0)
  		{
  			cache->hot_cache = true;
+ 
  			return cache;
  		}
  	}
  	/* not found, so insert a new cache */
! 	return sepgsql_avc_compute(scontext, (char *) tcontext, tclass);
  }
  
  /*
*************** sepgsql_avc_check_perms_label(const char
*** 337,357 ****
  	do {
  		result = true;
  
! 		/*
! 		 * If target object is unlabeled, we assume it has
! 		 * system 'unlabeled' security context instead.
! 		 */
! 		if (tcontext)
! 			cache = sepgsql_avc_lookup(scontext, tcontext, tclass);
! 		else
! 			cache = sepgsql_avc_lookup(scontext,
! 									   sepgsql_avc_unlabeled(), tclass);
  
  		denied = required & ~cache->allowed;
  
! 		/*
! 		 * Compute permissions to be audited
! 		 */
  		if (sepgsql_get_debug_audit())
  			audited = (denied ? (denied & ~0) : (required & ~0));
  		else
--- 331,341 ----
  	do {
  		result = true;
  
! 		cache = sepgsql_avc_lookup(scontext, (char *) tcontext, tclass);
  
  		denied = required & ~cache->allowed;
  
! 		/* Compute permissions to be audited */
  		if (sepgsql_get_debug_audit())
  			audited = (denied ? (denied & ~0) : (required & ~0));
  		else
*************** sepgsql_avc_check_perms_label(const char
*** 387,394 ****
  	{
  		sepgsql_audit_log(!!denied,
  						  cache->scontext,
! 						  cache->tcontext_is_valid ?
! 						  cache->tcontext : sepgsql_avc_unlabeled(),
  						  cache->tclass,
  						  audited,
  						  audit_name);
--- 371,377 ----
  	{
  		sepgsql_audit_log(!!denied,
  						  cache->scontext,
! 						  cache->tcontext,
  						  cache->tclass,
  						  audited,
  						  audit_name);
*************** sepgsql_avc_trusted_proc(Oid functionId)
*** 441,451 ****
  
  	sepgsql_avc_check_valid();
  	do {
! 		if (tcontext)
! 			cache = sepgsql_avc_lookup(scontext, tcontext,
! 									   SEPG_CLASS_DB_PROCEDURE);
! 		else
! 			cache = sepgsql_avc_lookup(scontext, sepgsql_avc_unlabeled(),
  									   SEPG_CLASS_DB_PROCEDURE);
  	} while (!sepgsql_avc_check_valid());
  
--- 424,430 ----
  
  	sepgsql_avc_check_valid();
  	do {
! 		cache = sepgsql_avc_lookup(scontext, tcontext,
  									   SEPG_CLASS_DB_PROCEDURE);
  	} while (!sepgsql_avc_check_valid());
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to