All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libsemanage/semanage - permission check for semanage
@ 2006-01-19 21:45 Joshua Brindle
  2006-01-19 22:45 ` Ivan Gyurdiev
                   ` (3 more replies)
  0 siblings, 4 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-01-19 21:45 UTC (permalink / raw)
  To: SELinux List; +Cc: selinuxdev, Stephen Smalley

[-- Attachment #1: Type: text/plain, Size: 858 bytes --]

- add semanage_can_write to libsemanage which does a silent check for
access on the active store, modules directory and binary policy
directory
- chance semanage_is_managed to use can_write instead of create_store
for access check
- add access check to seobject.py, in semanageRecord init
- remove dans UID == 0 check
- make the bottom level Makefile propagate install-pywrap target
- make install-pywrap target in libselinux depend on pywrap


It appears that the last commit didn't have make swigify run in
libsemanage so the generated swig wrappers were out of date, the ones in
this patch include my changes as well as the last ones.

Also, it seems that the current semanage is not disconnecting from the
store or freeing the handle. While this isn't too much of a problem
(aside from memory leaks) now, it will be in the future with the policy
server.

[-- Attachment #2: 1-semanage-write-check.diff --]
[-- Type: text/x-patch, Size: 13540 bytes --]

diff -purN -x.svn libselinux/src/Makefile libselinux/src/Makefile
--- libselinux/src/Makefile	2006-01-18 11:53:22.000000000 -0500
+++ libselinux/src/Makefile	2006-01-19 15:11:06.000000000 -0500
@@ -63,7 +63,7 @@ install: all 
 	install -m 755 $(LIBSO) $(SHLIBDIR)
 	cd $(LIBDIR) && ln -sf ../../`basename $(SHLIBDIR)`/$(LIBSO) $(TARGET)
 
-install-pywrap: 
+install-pywrap: pywrap
 	test -d $(PYTHONLIBDIR)/site-packages || install -m 755 -d $(PYTHONLIBDIR)/site-packages
 	install -m 755 $(SWIGFILES) $(PYTHONLIBDIR)/site-packages
 
diff -purN -x.svn libsemanage/include/semanage/handle.h libsemanage/include/semanage/handle.h
--- libsemanage/include/semanage/handle.h	2006-01-18 11:54:04.000000000 -0500
+++ libsemanage/include/semanage/handle.h	2006-01-19 16:33:23.000000000 -0500
@@ -100,6 +100,9 @@ int semanage_begin_transaction(semanage_
  */
 int semanage_commit(semanage_handle_t *);
 
+/* returns -1 if the store is probably not writable by the current UID/GID */
+int semanage_can_write(semanage_handle_t *sh);
+
 /* META NOTES
  *
  * For all functions a non-negative number indicates success. For some
diff -purN -x.svn libsemanage/src/direct_api.c libsemanage/src/direct_api.c
--- libsemanage/src/direct_api.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.c	2006-01-19 15:11:05.000000000 -0500
@@ -82,7 +82,8 @@ int semanage_direct_is_managed(semanage_
 	if (semanage_check_init(polpath))
 		goto err;
 
-	if (semanage_create_store(sh, 0) < 0) 
+	/* manage test should be silent */
+	if (semanage_can_write(sh) < 0) 
 		return 0;
 
 	return 1;
@@ -775,3 +776,9 @@ static int semanage_direct_list(semanage
         }
 	return retval;
 }
+
+/* returns -1 if the store or binary policy directory 
+ * is probably not writable by the current UID/GID */
+int semanage_direct_can_write(semanage_handle_t *sh) {
+	return semanage_store_writable(sh);
+}
diff -purN -x.svn libsemanage/src/direct_api.h libsemanage/src/direct_api.h
--- libsemanage/src/direct_api.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.h	2006-01-19 15:11:05.000000000 -0500
@@ -37,4 +37,6 @@ int semanage_direct_connect(
 int semanage_direct_is_managed(
 	struct semanage_handle *sh);
 
+int semanage_direct_can_write(struct semanage_handle *sh);
+
 #endif
diff -purN -x.svn libsemanage/src/handle.c libsemanage/src/handle.c
--- libsemanage/src/handle.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle.c	2006-01-19 16:33:33.000000000 -0500
@@ -142,6 +142,20 @@ int semanage_connect(semanage_handle_t *
 	return 0;
 }
 
+int semanage_can_write(semanage_handle_t *sh) {
+	assert(sh != NULL);
+	switch (sh->conf->store_type) {
+	case SEMANAGE_CON_DIRECT: 
+		return semanage_direct_can_write(sh);
+	default:
+		return -1;
+	}
+
+	return -1; /* unreachable */
+}
+
+hidden_def(semanage_can_write)
+
 int semanage_disconnect(semanage_handle_t *sh) {
 	assert(sh != NULL && sh->funcs != NULL && sh->funcs->disconnect != NULL);
 	if (!sh->is_connected) {
diff -purN -x.svn libsemanage/src/handle_internal.h libsemanage/src/handle_internal.h
--- libsemanage/src/handle_internal.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle_internal.h	2006-01-19 11:37:11.000000000 -0500
@@ -7,5 +7,6 @@
 hidden_proto(semanage_begin_transaction)
 hidden_proto(semanage_handle_destroy)
 hidden_proto(semanage_reload_policy)
+hidden_proto(semanage_can_write)
 
 #endif
diff -purN -x.svn libsemanage/src/libsemanage.map libsemanage/src/libsemanage.map
--- libsemanage/src/libsemanage.map	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/libsemanage.map	2006-01-19 11:37:24.000000000 -0500
@@ -11,6 +11,6 @@ LIBSEMANAGE_1.0 {
 	  semanage_reload_policy; semanage_set_reload; semanage_set_rebuild;
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
-	  semanage_fcontext_*;
+	  semanage_fcontext_*; semanage_can_write;
   local: *;
 };
diff -purN -x.svn libsemanage/src/semanage.py libsemanage/src/semanage.py
--- libsemanage/src/semanage.py	2006-01-19 15:45:19.000000000 -0500
+++ libsemanage/src/semanage.py	2006-01-19 15:43:18.000000000 -0500
@@ -88,6 +88,8 @@ semanage_begin_transaction = _semanage.s
 
 semanage_commit = _semanage.semanage_commit
 
+semanage_can_write = _semanage.semanage_can_write
+
 semanage_module_install = _semanage.semanage_module_install
 
 semanage_module_upgrade = _semanage.semanage_module_upgrade
@@ -258,6 +260,10 @@ semanage_user_get_name = _semanage.seman
 
 semanage_user_set_name = _semanage.semanage_user_set_name
 
+semanage_user_get_prefix = _semanage.semanage_user_get_prefix
+
+semanage_user_set_prefix = _semanage.semanage_user_set_prefix
+
 semanage_user_get_mlslevel = _semanage.semanage_user_get_mlslevel
 
 semanage_user_set_mlslevel = _semanage.semanage_user_set_mlslevel
diff -purN -x.svn libsemanage/src/semanage_store.c libsemanage/src/semanage_store.c
--- libsemanage/src/semanage_store.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.c	2006-01-19 16:36:53.000000000 -0500
@@ -281,7 +281,41 @@ int semanage_create_store(semanage_handl
 	return 0;
 }
 
+/* returns -1 if the store or binary policy directory 
+ * is probably not writable by the current UID/GID */
+int semanage_store_writable(semanage_handle_t *sh) {
+	const char *path;
+	char *path2, *path3, polpath[PATH_MAX];
+	int rc;
 
+	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), sh->conf->store_path);
+
+	if (semanage_check_init(polpath))
+		return -1;
+
+	/* check the active directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
+	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
+		return rc;
+
+	/* check the binary policy install directory */
+	path = selinux_binary_policy_path();
+	path2 = strdup(path);
+	path3 = dirname(path2);
+
+	if ((rc = access(path3, R_OK | W_OK | X_OK)) != 0) {
+		free(path2);
+		return rc;
+	}
+	free(path2);
+
+	/* check the modules directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
+		return rc;
+	
+	return 0;
+}
 
 /********************* other I/O functions *********************/
 
diff -purN -x.svn libsemanage/src/semanage_store.h libsemanage/src/semanage_store.h
--- libsemanage/src/semanage_store.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.h	2006-01-19 15:11:05.000000000 -0500
@@ -99,5 +99,6 @@ int semanage_verify_modules(
 int semanage_verify_linked(semanage_handle_t *sh);
 int semanage_verify_kernel(semanage_handle_t *sh);
 int semanage_split_fc(semanage_handle_t *sh);
+int semanage_store_writable(semanage_handle_t *sh);
 
 #endif
diff -purN -x.svn libsemanage/src/semanageswig_wrap.c libsemanage/src/semanageswig_wrap.c
--- libsemanage/src/semanageswig_wrap.c	2006-01-19 15:45:19.000000000 -0500
+++ libsemanage/src/semanageswig_wrap.c	2006-01-19 15:43:18.000000000 -0500
@@ -1748,6 +1748,8 @@ int semanage_user_compare(semanage_user_
 int semanage_user_compare2(semanage_user_t const *,semanage_user_t const *);
 char const *semanage_user_get_name(semanage_user_t const *);
 int semanage_user_set_name(semanage_handle_t *,semanage_user_t *,char const *);
+char const *semanage_user_get_prefix(semanage_user_t const *);
+int semanage_user_set_prefix(semanage_handle_t *,semanage_user_t *,char const *);
 char const *semanage_user_get_mlslevel(semanage_user_t const *);
 int semanage_user_set_mlslevel(semanage_handle_t *,semanage_user_t *,char const *);
 char const *semanage_user_get_mlsrange(semanage_user_t const *);
@@ -2396,6 +2398,26 @@ static PyObject *_wrap_semanage_commit(P
 }
 
 
+static PyObject *_wrap_semanage_can_write(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
+    int result;
+    PyObject * obj0 = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"O:semanage_can_write",&obj0)) goto fail;
+    SWIG_Python_ConvertPtr(obj0, (void **)&arg1, SWIGTYPE_p_semanage_handle, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(1)) SWIG_fail;
+    result = (int)semanage_can_write(arg1);
+    
+    {
+        resultobj = SWIG_From_int((int)(result)); 
+    }
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyObject *_wrap_semanage_module_install(PyObject *self, PyObject *args) {
     PyObject *resultobj;
     semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
@@ -4658,6 +4680,53 @@ static PyObject *_wrap_semanage_user_set
 }
 
 
+static PyObject *_wrap_semanage_user_get_prefix(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    semanage_user_t *arg1 = (semanage_user_t *) 0 ;
+    char *result;
+    PyObject * obj0 = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"O:semanage_user_get_prefix",&obj0)) goto fail;
+    SWIG_Python_ConvertPtr(obj0, (void **)&arg1, SWIGTYPE_p_semanage_user, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(1)) SWIG_fail;
+    result = (char *)semanage_user_get_prefix((semanage_user_t const *)arg1);
+    
+    resultobj = SWIG_FromCharPtr(result);
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
+static PyObject *_wrap_semanage_user_set_prefix(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
+    semanage_user_t *arg2 = (semanage_user_t *) 0 ;
+    char *arg3 = (char *) 0 ;
+    int result;
+    PyObject * obj0 = 0 ;
+    PyObject * obj1 = 0 ;
+    PyObject * obj2 = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"OOO:semanage_user_set_prefix",&obj0,&obj1,&obj2)) goto fail;
+    SWIG_Python_ConvertPtr(obj0, (void **)&arg1, SWIGTYPE_p_semanage_handle, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(1)) SWIG_fail;
+    SWIG_Python_ConvertPtr(obj1, (void **)&arg2, SWIGTYPE_p_semanage_user, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(2)) SWIG_fail;
+    if (!SWIG_AsCharPtr(obj2, (char**)&arg3)) {
+        SWIG_arg_fail(3);SWIG_fail;
+    }
+    result = (int)semanage_user_set_prefix(arg1,arg2,(char const *)arg3);
+    
+    {
+        resultobj = SWIG_From_int((int)(result)); 
+    }
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyObject *_wrap_semanage_user_get_mlslevel(PyObject *self, PyObject *args) {
     PyObject *resultobj;
     semanage_user_t *arg1 = (semanage_user_t *) 0 ;
@@ -7423,6 +7492,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"semanage_disconnect", _wrap_semanage_disconnect, METH_VARARGS, NULL},
 	 { (char *)"semanage_begin_transaction", _wrap_semanage_begin_transaction, METH_VARARGS, NULL},
 	 { (char *)"semanage_commit", _wrap_semanage_commit, METH_VARARGS, NULL},
+	 { (char *)"semanage_can_write", _wrap_semanage_can_write, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install", _wrap_semanage_module_install, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_upgrade", _wrap_semanage_module_upgrade, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install_base", _wrap_semanage_module_install_base, METH_VARARGS, NULL},
@@ -7508,6 +7578,8 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"semanage_user_compare2", _wrap_semanage_user_compare2, METH_VARARGS, NULL},
 	 { (char *)"semanage_user_get_name", _wrap_semanage_user_get_name, METH_VARARGS, NULL},
 	 { (char *)"semanage_user_set_name", _wrap_semanage_user_set_name, METH_VARARGS, NULL},
+	 { (char *)"semanage_user_get_prefix", _wrap_semanage_user_get_prefix, METH_VARARGS, NULL},
+	 { (char *)"semanage_user_set_prefix", _wrap_semanage_user_set_prefix, METH_VARARGS, NULL},
 	 { (char *)"semanage_user_get_mlslevel", _wrap_semanage_user_get_mlslevel, METH_VARARGS, NULL},
 	 { (char *)"semanage_user_set_mlslevel", _wrap_semanage_user_set_mlslevel, METH_VARARGS, NULL},
 	 { (char *)"semanage_user_get_mlsrange", _wrap_semanage_user_get_mlsrange, METH_VARARGS, NULL},
diff -purN -x.svn Makefile Makefile
--- Makefile	2005-10-13 13:36:35.000000000 -0400
+++ Makefile	2006-01-19 15:46:30.000000000 -0500
@@ -1,4 +1,5 @@
 SUBDIRS=libsepol libselinux libsemanage checkpolicy policycoreutils # policy
+PYSUBDIRS=libselinux libsemanage
 
 ifeq ($(DEBUG),1)
 	export CFLAGS = -g3 -O0 -gdwarf-2 -fno-strict-aliasing -Wall -Wshadow
@@ -9,7 +10,11 @@ install relabel: 
 	@for subdir in $(SUBDIRS); do \
 		(cd $$subdir && $(MAKE) $@) || exit 1; \
 	done
-#	cd policy && make install-src
+
+install-pywrap:
+	@for subdir in $(PYSUBDIRS); do \
+		(cd $$subdir && $(MAKE) $@) || exit 1; \
+	done
 
 clean:
 	@for subdir in $(SUBDIRS); do \
diff -purN -x.svn policycoreutils/semanage/semanage policycoreutils/semanage/semanage
--- policycoreutils/semanage/semanage	2006-01-19 15:04:23.000000000 -0500
+++ policycoreutils/semanage/semanage	2006-01-19 15:11:06.000000000 -0500
@@ -24,9 +24,6 @@ import os, sys, getopt
 import seobject
 
 if __name__ == '__main__':
-	if os.getuid() > 0 or os.geteuid() > 0:
-		print "You must be root to run %s." % sys.argv[0]
-		sys.exit(0)
 
 	def usage(message = ""):
 		print '\
diff -purN -x.svn policycoreutils/semanage/seobject.py policycoreutils/semanage/seobject.py
--- policycoreutils/semanage/seobject.py	2006-01-19 15:04:23.000000000 -0500
+++ policycoreutils/semanage/seobject.py	2006-01-19 16:34:36.000000000 -0500
@@ -142,6 +142,11 @@ class setransRecords:
 class semanageRecords:
 	def __init__(self):
 		self.sh = semanage_handle_create()
+		rc = semanage_can_write(self.sh)
+		if rc:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Cannot write to policy directory.")
+
 		self.semanaged = semanage_is_managed(self.sh)
 		if self.semanaged:
 			semanage_connect(self.sh)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-19 21:45 [PATCH] libsemanage/semanage - permission check for semanage Joshua Brindle
@ 2006-01-19 22:45 ` Ivan Gyurdiev
  2006-01-20  1:38   ` Joshua Brindle
  2006-01-20 13:54 ` Stephen Smalley
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 25+ messages in thread
From: Ivan Gyurdiev @ 2006-01-19 22:45 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: SELinux List, selinuxdev, Stephen Smalley


> - chance semanage_is_managed to use can_write instead of create_store
> for access check
>   
Why should semanage_is_managed do an access check?
How does the lack of access mean that the store isn't managed?
I see in seobject, both is_managed, and can_write are called now, 
meaning two access checks
(and shouldn't they be in the opposite order).



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-19 22:45 ` Ivan Gyurdiev
@ 2006-01-20  1:38   ` Joshua Brindle
  2006-01-20  2:11     ` Ivan Gyurdiev
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20  1:38 UTC (permalink / raw)
  To: Ivan Gyurdiev; +Cc: SELinux List, selinuxdev, Stephen Smalley

Ivan Gyurdiev wrote:
> 
>> - chance semanage_is_managed to use can_write instead of create_store
>> for access check
>>   
> 
> Why should semanage_is_managed do an access check?
the only way to check for a managed policy is to look for the 
directories. We also require write access to read from the store (read 
lock) so you can't do anything if you can't write to it. Also, it was 
already doing access checks (semanage_create_store with argument 0 
checks access but doesn't create directories) and that was what was 
spamming the user with errors when they couldn't write.

> How does the lack of access mean that the store isn't managed?

for all intents and purposes yes, since you can't query or write to it.

> I see in seobject, both is_managed, and can_write are called now, 
> meaning two access checks
> (and shouldn't they be in the opposite order).
> 

I'd like to bail as soon as possible if you aren't going to be able to 
write. Since they both do essentially the same checks but can_write is 
silent it should be first so that the user doesn't see the debug errors.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20  1:38   ` Joshua Brindle
@ 2006-01-20  2:11     ` Ivan Gyurdiev
  2006-01-20  2:19       ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Ivan Gyurdiev @ 2006-01-20  2:11 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: SELinux List, selinuxdev, Stephen Smalley


>> How does the lack of access mean that the store isn't managed?
>
> for all intents and purposes yes, since you can't query or write to it.
I still think that you shouldn't draw conclusions about what the user 
will be doing with the store in a function that answers the question "Is 
the store managed?" Maybe I'll switch to a more privileged user when I 
decide to query or write to the store.
>> I see in seobject, both is_managed, and can_write are called now, 
>> meaning two access checks
>> (and shouldn't they be in the opposite order).
>>
>
> I'd like to bail as soon as possible if you aren't going to be able to 
> write. Since they both do essentially the same checks but can_write is 
> silent it should be first so that the user doesn't see the debug errors.
This doesn't make sense to me, is_managed() should also be silent in the 
success path (meaning, if it can successfully check if the store is 
managed or not).

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20  2:11     ` Ivan Gyurdiev
@ 2006-01-20  2:19       ` Joshua Brindle
  0 siblings, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20  2:19 UTC (permalink / raw)
  To: Ivan Gyurdiev; +Cc: SELinux List, selinuxdev, Stephen Smalley

Ivan Gyurdiev wrote:
> 
>>> How does the lack of access mean that the store isn't managed?
>>
>>
>> for all intents and purposes yes, since you can't query or write to it.
> 
> I still think that you shouldn't draw conclusions about what the user 
> will be doing with the store in a function that answers the question "Is 
> the store managed?" Maybe I'll switch to a more privileged user when I 
> decide to query or write to the store.
> 
I guess I can use access R_OK | X_OK to see if it's managed but 
ultimately the user won't be able to do anything if they can't write.

>>> I see in seobject, both is_managed, and can_write are called now, 
>>> meaning two access checks
>>> (and shouldn't they be in the opposite order).
>>>
>>
>> I'd like to bail as soon as possible if you aren't going to be able to 
>> write. Since they both do essentially the same checks but can_write is 
>> silent it should be first so that the user doesn't see the debug errors.
> 
> This doesn't make sense to me, is_managed() should also be silent in the 
> success path (meaning, if it can successfully check if the store is 
> managed or not).
> 
the reason Dan put in the UID == 0 check that I was trying to get rid of 
was because failure to read/write to the store spammed the user with 
error messages that don't make any sense to a user. Checking if they can 
  write before attempting to do so is all that makes sense, which is 
what I did. is_managed was always silent in the success path, it was not 
in the failure path which is why i switched it to use can_write instead 
of create_store, which has ERR() in all failure paths.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-19 21:45 [PATCH] libsemanage/semanage - permission check for semanage Joshua Brindle
  2006-01-19 22:45 ` Ivan Gyurdiev
@ 2006-01-20 13:54 ` Stephen Smalley
  2006-01-20 14:00   ` Joshua Brindle
  2006-01-20 14:09 ` Stephen Smalley
  2006-01-20 15:20 ` Stephen Smalley
  3 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-20 13:54 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Thu, 2006-01-19 at 16:45 -0500, Joshua Brindle wrote:
> - add semanage_can_write to libsemanage which does a silent check for
> access on the active store, modules directory and binary policy
> directory
> - chance semanage_is_managed to use can_write instead of create_store
> for access check
> - add access check to seobject.py, in semanageRecord init
> - remove dans UID == 0 check
> - make the bottom level Makefile propagate install-pywrap target
> - make install-pywrap target in libselinux depend on pywrap
> 
> 
> It appears that the last commit didn't have make swigify run in
> libsemanage so the generated swig wrappers were out of date, the ones in
> this patch include my changes as well as the last ones.
> 
> Also, it seems that the current semanage is not disconnecting from the
> store or freeing the handle. While this isn't too much of a problem
> (aside from memory leaks) now, it will be in the future with the policy
> server.

diff -purN -x.svn libsemanage/include/semanage/handle.h libsemanage/include/semanage/handle.h
--- libsemanage/include/semanage/handle.h	2006-01-18 11:54:04.000000000 -0500
+++ libsemanage/include/semanage/handle.h	2006-01-19 16:33:23.000000000 -0500
@@ -100,6 +100,9 @@ int semanage_begin_transaction(semanage_
  */
 int semanage_commit(semanage_handle_t *);
 
+/* returns -1 if the store is probably not writable by the current UID/GID */
+int semanage_can_write(semanage_handle_t *sh);

The comment might be a little misleading, as:
a) access(2) checks against the real UID/GID of the process, not its
effective or fs identities; not presently an issue since the caller is
not a setuid or setgid program, but could be an issue at some point,
b) access(2) internally calls permission(9), and permission(9) calls the
security hook, so SELinux checks are also applied here.

diff -purN -x.svn libsemanage/src/semanage_store.c libsemanage/src/semanage_store.c
--- libsemanage/src/semanage_store.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.c	2006-01-19 16:36:53.000000000 -0500
@@ -281,7 +281,41 @@ int semanage_create_store(semanage_handl
 	return 0;
 }
 
+/* returns -1 if the store or binary policy directory 
+ * is probably not writable by the current UID/GID */
+int semanage_store_writable(semanage_handle_t *sh) {

Ditto.

+	const char *path;
+	char *path2, *path3, polpath[PATH_MAX];
+	int rc;
 
+	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), sh->conf->store_path);
+
+	if (semanage_check_init(polpath))
+		return -1;

These calls presently occur from semanage_direct* functions only, prior
to calling semanage_create_store.  Not sure why this would be different.
+
+	/* check the active directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
+	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
+		return rc;
+
+	/* check the binary policy install directory */
+	path = selinux_binary_policy_path();
+	path2 = strdup(path);
+	path3 = dirname(path2);
+
+	if ((rc = access(path3, R_OK | W_OK | X_OK)) != 0) {
+		free(path2);
+		return rc;
+	}
+	free(path2);

Not sure about requiring rwx to the installed policy directory for this
test.  As far as DAC permissions are concerned, this ends up being
equivalent presently to checking rwx to the module store, as they are
both root owned and only writable by owner, but conceptually being able
to manipulate the store (particularly for read ops) differs from being
able to install a new policy.  SELinux policy might allow one but not
the other.

+
+	/* check the modules directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
+		return rc;
+	
+	return 0;
+}

Do we need both checks (active toplevel and active modules), or will one do?
semanage_create_store() ends up doing multiple checks since it also
creates the directories along the way, but if we are just checking
access, it is likely sufficient to check the most restrictive one (i.e.
active modules), right?
 
 /********************* other I/O functions *********************/
 
diff -purN -x.svn policycoreutils/semanage/seobject.py policycoreutils/semanage/seobject.py
--- policycoreutils/semanage/seobject.py	2006-01-19 15:04:23.000000000 -0500
+++ policycoreutils/semanage/seobject.py	2006-01-19 16:34:36.000000000 -0500
@@ -142,6 +142,11 @@ class setransRecords:
 class semanageRecords:
 	def __init__(self):
 		self.sh = semanage_handle_create()
+		rc = semanage_can_write(self.sh)
+		if rc:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Cannot write to policy directory.")
+
 		self.semanaged = semanage_is_managed(self.sh)
 		if self.semanaged:
 			semanage_connect(self.sh)

Particularly given that this is called from __init__, it seems like the
check on the installed policy directory is too strong, as it could
interfere with module store read operations.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 13:54 ` Stephen Smalley
@ 2006-01-20 14:00   ` Joshua Brindle
  2006-01-20 14:24     ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20 14:00 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
<snip>

> 
> The comment might be a little misleading, as:
> a) access(2) checks against the real UID/GID of the process, not its
> effective or fs identities; not presently an issue since the caller is
> not a setuid or setgid program, but could be an issue at some point,
> b) access(2) internally calls permission(9), and permission(9) calls the
> security hook, so SELinux checks are also applied here.
> 
Ok, that can be removed/updated. It is better IMO that the selinux 
checks apply since those will be just as much or more of an issue than 
uid/gid on a strict system

> diff -purN -x.svn libsemanage/src/semanage_store.c libsemanage/src/semanage_store.c
> --- libsemanage/src/semanage_store.c	2006-01-18 11:56:33.000000000 -0500
> +++ libsemanage/src/semanage_store.c	2006-01-19 16:36:53.000000000 -0500
> @@ -281,7 +281,41 @@ int semanage_create_store(semanage_handl
>  	return 0;
>  }
>  
> +/* returns -1 if the store or binary policy directory 
> + * is probably not writable by the current UID/GID */
> +int semanage_store_writable(semanage_handle_t *sh) {
> 
> Ditto.
> 
same

> +	const char *path;
> +	char *path2, *path3, polpath[PATH_MAX];
> +	int rc;
>  
> +	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), sh->conf->store_path);
> +
> +	if (semanage_check_init(polpath))
> +		return -1;
> 
> These calls presently occur from semanage_direct* functions only, prior
> to calling semanage_create_store.  Not sure why this would be different.

semanage_can_write can be called separately. See the seobject.py patch 
which calls it before anything that calls semanage_check_init. I suppose 
I can move it to the direct_can_write but it is an semanage_store 
function and this will only be called by direct_can_hook, not by ps or 
any other api

> +
> +	/* check the active directory */
> +	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
> +	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
> +		return rc;
> +
> +	/* check the binary policy install directory */
> +	path = selinux_binary_policy_path();
> +	path2 = strdup(path);
> +	path3 = dirname(path2);
> +
> +	if ((rc = access(path3, R_OK | W_OK | X_OK)) != 0) {
> +		free(path2);
> +		return rc;
> +	}
> +	free(path2);
> 
> Not sure about requiring rwx to the installed policy directory for this
> test.  As far as DAC permissions are concerned, this ends up being
> equivalent presently to checking rwx to the module store, as they are
> both root owned and only writable by owner, but conceptually being able
> to manipulate the store (particularly for read ops) differs from being
> able to install a new policy.  SELinux policy might allow one but not
> the other.
> 
hrm, at some point we need to test the writability of the binary policy 
dir. If the whole commit goes through and then the policy can't be 
written there is a consistency issue on the system


> +
> +	/* check the modules directory */
> +	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
> +	if ((rc = access(path, R_OK | W_OK | X_OK)) != 0)
> +		return rc;
> +	
> +	return 0;
> +}
> 
> Do we need both checks (active toplevel and active modules), or will one do?
> semanage_create_store() ends up doing multiple checks since it also
> creates the directories along the way, but if we are just checking
> access, it is likely sufficient to check the most restrictive one (i.e.
> active modules), right?
>  
sure.

>  /********************* other I/O functions *********************/
>  
> diff -purN -x.svn policycoreutils/semanage/seobject.py policycoreutils/semanage/seobject.py
> --- policycoreutils/semanage/seobject.py	2006-01-19 15:04:23.000000000 -0500
> +++ policycoreutils/semanage/seobject.py	2006-01-19 16:34:36.000000000 -0500
> @@ -142,6 +142,11 @@ class setransRecords:
>  class semanageRecords:
>  	def __init__(self):
>  		self.sh = semanage_handle_create()
> +		rc = semanage_can_write(self.sh)
> +		if rc:
> +			semanage_handle_destroy(self.sh)
> +			raise ValueError("Cannot write to policy directory.")
> +
>  		self.semanaged = semanage_is_managed(self.sh)
>  		if self.semanaged:
>  			semanage_connect(self.sh)
> 
> Particularly given that this is called from __init__, it seems like the
> check on the installed policy directory is too strong, as it could
> interfere with module store read operations.
> 

fair enough, I'll rebase a patch today with these concerns addressed

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 14:09 ` Stephen Smalley
@ 2006-01-20 14:04   ` Joshua Brindle
  0 siblings, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20 14:04 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Thu, 2006-01-19 at 16:45 -0500, Joshua Brindle wrote:
> 
>>- add semanage_can_write to libsemanage which does a silent check for
>>access on the active store, modules directory and binary policy
>>directory
>>- chance semanage_is_managed to use can_write instead of create_store
>>for access check
>>- add access check to seobject.py, in semanageRecord init
> 
> 
> Also, how do you envision implementing this interface for the policy
> server backend?  Same question exists for semanage_is_managed I suppose,
> but that interface seems a little more general in concept.
>   

I wasn't at first but one could always ask the server if my context has 
write permission to the policy, which is a slightly different concept 
but from a user perspective probably means the same thing.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-19 21:45 [PATCH] libsemanage/semanage - permission check for semanage Joshua Brindle
  2006-01-19 22:45 ` Ivan Gyurdiev
  2006-01-20 13:54 ` Stephen Smalley
@ 2006-01-20 14:09 ` Stephen Smalley
  2006-01-20 14:04   ` Joshua Brindle
  2006-01-20 15:20 ` Stephen Smalley
  3 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-20 14:09 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Thu, 2006-01-19 at 16:45 -0500, Joshua Brindle wrote:
> - add semanage_can_write to libsemanage which does a silent check for
> access on the active store, modules directory and binary policy
> directory
> - chance semanage_is_managed to use can_write instead of create_store
> for access check
> - add access check to seobject.py, in semanageRecord init

Also, how do you envision implementing this interface for the policy
server backend?  Same question exists for semanage_is_managed I suppose,
but that interface seems a little more general in concept.
  
-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 14:00   ` Joshua Brindle
@ 2006-01-20 14:24     ` Stephen Smalley
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Smalley @ 2006-01-20 14:24 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Fri, 2006-01-20 at 09:00 -0500, Joshua Brindle wrote:
> semanage_can_write can be called separately. See the seobject.py patch 
> which calls it before anything that calls semanage_check_init. I suppose 
> I can move it to the direct_can_write but it is an semanage_store 
> function and this will only be called by direct_can_hook, not by ps or 
> any other api

Right, I was just looking for consistency in where check_init is called,
and presently it seems to always be done by the direct "layer" rather
than the store "layer".  

> hrm, at some point we need to test the writability of the binary policy 
> dir. If the whole commit goes through and then the policy can't be 
> written there is a consistency issue on the system

You already have rollback code, so the store should be rolled back to
the previous state which would already be consistent with the installed
policy.  You'd get two failure messages on both attempts to install the
binary policy file (first the new one, then the rolled back one), but
since it should already match the one from the previous sandbox, it
should be consistent nonetheless.

In any event, we shouldn't require write access to the policy directory
for all libsemanage operations.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-19 21:45 [PATCH] libsemanage/semanage - permission check for semanage Joshua Brindle
                   ` (2 preceding siblings ...)
  2006-01-20 14:09 ` Stephen Smalley
@ 2006-01-20 15:20 ` Stephen Smalley
  2006-01-20 19:14   ` Joshua Brindle
  3 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-20 15:20 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: SELinux List, selinuxdev

On Thu, 2006-01-19 at 16:45 -0500, Joshua Brindle wrote:
> - make the bottom level Makefile propagate install-pywrap target
> - make install-pywrap target in libselinux depend on pywrap
> 
> 
> It appears that the last commit didn't have make swigify run in
> libsemanage so the generated swig wrappers were out of date, the ones in
> this patch include my changes as well as the last ones.

Merged the pywrap Makefile changes and regenerated the wrappers for the
prior changes.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 15:20 ` Stephen Smalley
@ 2006-01-20 19:14   ` Joshua Brindle
  2006-01-20 20:49     ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20 19:14 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: SELinux List, selinuxdev

[-- Attachment #1: Type: text/plain, Size: 1160 bytes --]

On Fri, 2006-01-20 at 10:20 -0500, Stephen Smalley wrote:
> On Thu, 2006-01-19 at 16:45 -0500, Joshua Brindle wrote:
> > - make the bottom level Makefile propagate install-pywrap target
> > - make install-pywrap target in libselinux depend on pywrap
> > 
> > 
> > It appears that the last commit didn't have make swigify run in
> > libsemanage so the generated swig wrappers were out of date, the ones in
> > this patch include my changes as well as the last ones.
> 
> Merged the pywrap Makefile changes and regenerated the wrappers for the
> prior changes.
> 

attached patch addresses all of the concerns with the prior patch. The
main change is to make a function called semanage_access_check that
returns error, existance, readable or writable. Depending on where the
check is done test against one of them. 

I am now able to query the store as a non-root user after giving read
access to /modules and /modules/active{,/*} and read/write to
modules/semanage.read.LOCK

as expected I can query the store but not write to it, I also added a
check for writability at the beginning of begin_transaction so that the
user gets a nicer error when this happens.

[-- Attachment #2: 1-semanage-write-check.diff --]
[-- Type: text/x-patch, Size: 10699 bytes --]

diff -purN -x.svn libsemanage/include/semanage/handle.h libsemanage/include/semanage/handle.h
--- libsemanage/include/semanage/handle.h	2006-01-18 11:54:04.000000000 -0500
+++ libsemanage/include/semanage/handle.h	2006-01-20 09:43:33.000000000 -0500
@@ -100,6 +100,12 @@ int semanage_begin_transaction(semanage_
  */
 int semanage_commit(semanage_handle_t *);
 
+#define SEMANAGE_CAN_READ 1
+#define SEMANAGE_CAN_WRITE 2
+/* returns SEMANAGE_CAN_READ or SEMANAGE_CAN_WRITE if the store is readable
+ * or writable, respectively. <0 if an error occured */ 
+int semanage_access_check(semanage_handle_t *sh);
+
 /* META NOTES
  *
  * For all functions a non-negative number indicates success. For some
diff -purN -x.svn libsemanage/src/direct_api.c libsemanage/src/direct_api.c
--- libsemanage/src/direct_api.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.c	2006-01-20 11:34:14.000000000 -0500
@@ -82,7 +82,7 @@ int semanage_direct_is_managed(semanage_
 	if (semanage_check_init(polpath))
 		goto err;
 
-	if (semanage_create_store(sh, 0) < 0) 
+	if (semanage_access_check(sh) < 0) 
 		return 0;
 
 	return 1;
@@ -102,7 +102,7 @@ int semanage_direct_connect(semanage_han
 	if (semanage_check_init(polpath))
 		goto err;
 
-	if (semanage_create_store(sh, 1) < 0) 
+	if (semanage_access_check(sh) < SEMANAGE_CAN_READ) 
 		goto err;
 
 	sh->u.direct.translock_file_fd = -1;
@@ -226,6 +226,10 @@ static int semanage_direct_disconnect(se
 }
 
 static int semanage_direct_begintrans(semanage_handle_t *sh) {
+	
+	if (semanage_access_check(sh) != SEMANAGE_CAN_WRITE) {
+		return -1;
+	}
 	if (semanage_get_trans_lock(sh) < 0) {
 		return -1;
 	}
@@ -775,3 +779,14 @@ static int semanage_direct_list(semanage
         }
 	return retval;
 }
+
+int semanage_direct_access_check(semanage_handle_t *sh) {
+	char polpath[PATH_MAX];	
+
+	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), sh->conf->store_path);
+
+	if (semanage_check_init(polpath))
+		return -1;
+
+	return semanage_store_access_check(sh);
+}
diff -purN -x.svn libsemanage/src/direct_api.h libsemanage/src/direct_api.h
--- libsemanage/src/direct_api.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.h	2006-01-20 09:29:06.000000000 -0500
@@ -37,4 +37,6 @@ int semanage_direct_connect(
 int semanage_direct_is_managed(
 	struct semanage_handle *sh);
 
+int semanage_direct_access_check(struct semanage_handle *sh);
+
 #endif
diff -purN -x.svn libsemanage/src/handle.c libsemanage/src/handle.c
--- libsemanage/src/handle.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle.c	2006-01-20 09:26:57.000000000 -0500
@@ -142,6 +142,19 @@ int semanage_connect(semanage_handle_t *
 	return 0;
 }
 
+int semanage_access_check(semanage_handle_t *sh) {
+	assert(sh != NULL);
+	switch (sh->conf->store_type) {
+	case SEMANAGE_CON_DIRECT: 
+		return semanage_direct_access_check(sh);
+	default:
+		return -1;
+	}
+
+	return -1; /* unreachable */
+}
+hidden_def(semanage_access_check)
+
 int semanage_disconnect(semanage_handle_t *sh) {
 	assert(sh != NULL && sh->funcs != NULL && sh->funcs->disconnect != NULL);
 	if (!sh->is_connected) {
diff -purN -x.svn libsemanage/src/handle_internal.h libsemanage/src/handle_internal.h
--- libsemanage/src/handle_internal.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle_internal.h	2006-01-20 09:29:19.000000000 -0500
@@ -7,5 +7,6 @@
 hidden_proto(semanage_begin_transaction)
 hidden_proto(semanage_handle_destroy)
 hidden_proto(semanage_reload_policy)
+hidden_proto(semanage_access_check)
 
 #endif
diff -purN -x.svn libsemanage/src/libsemanage.map libsemanage/src/libsemanage.map
--- libsemanage/src/libsemanage.map	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/libsemanage.map	2006-01-20 09:27:13.000000000 -0500
@@ -11,6 +11,6 @@ LIBSEMANAGE_1.0 {
 	  semanage_reload_policy; semanage_set_reload; semanage_set_rebuild;
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
-	  semanage_fcontext_*;
+	  semanage_fcontext_*; semanage_access_check;
   local: *;
 };
diff -purN -x.svn libsemanage/src/semanage.py libsemanage/src/semanage.py
--- libsemanage/src/semanage.py	2006-01-20 11:30:59.000000000 -0500
+++ libsemanage/src/semanage.py	2006-01-20 11:42:19.000000000 -0500
@@ -87,6 +87,10 @@ semanage_disconnect = _semanage.semanage
 semanage_begin_transaction = _semanage.semanage_begin_transaction
 
 semanage_commit = _semanage.semanage_commit
+SEMANAGE_CAN_READ = _semanage.SEMANAGE_CAN_READ
+SEMANAGE_CAN_WRITE = _semanage.SEMANAGE_CAN_WRITE
+
+semanage_access_check = _semanage.semanage_access_check
 
 semanage_module_install = _semanage.semanage_module_install
 
diff -purN -x.svn libsemanage/src/semanage_store.c libsemanage/src/semanage_store.c
--- libsemanage/src/semanage_store.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.c	2006-01-20 11:28:36.000000000 -0500
@@ -281,7 +281,54 @@ int semanage_create_store(semanage_handl
 	return 0;
 }
 
+/* returns <0 if the active store cannot be read or doesn't exist
+ * 0 if the store exists but the lock file cannot be written to
+ * SEMANAGE_CAN_READ if the store can be read and the lock file written to
+ * SEMANAGE_CAN_WRITE if the modules directory and binary policy dir can be written to
+ */
+int semanage_store_access_check(semanage_handle_t *sh) {
+	const char *path;
+	char *path2, *path3;
+	int rc = -1;
+
+	/* read access on active store */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
+	if (access(path, R_OK | X_OK) != 0)
+		goto out;
+
+	/* we can read the active store meaning it is managed
+	 * so now we return 0 to indicate no error */
+	rc = 0;
+
+	/* read/write access on lock file required for reading */
+	path = semanage_files[SEMANAGE_READ_LOCK];
+	if (access(path, R_OK | W_OK) != 0)
+		goto out;
+
+	/* everything needed for reading has been checked */
+	rc = SEMANAGE_CAN_READ;
+
+	/* check the modules directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	if (access(path, R_OK | W_OK | X_OK) != 0)
+		goto out;
+
+	/* check the binary policy install directory */
+	path = selinux_binary_policy_path();
+	path2 = strdup(path);
+	path3 = dirname(path2);
+
+	if ((access(path3, R_OK | W_OK | X_OK)) != 0) {
+		free(path2);
+		goto out;
+	}
+	free(path2);
+	
+	rc = SEMANAGE_CAN_WRITE;
 
+out:
+	return rc;
+}
 
 /********************* other I/O functions *********************/
 
diff -purN -x.svn libsemanage/src/semanage_store.h libsemanage/src/semanage_store.h
--- libsemanage/src/semanage_store.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.h	2006-01-19 15:11:05.000000000 -0500
@@ -99,5 +99,6 @@ int semanage_verify_modules(
 int semanage_verify_linked(semanage_handle_t *sh);
 int semanage_verify_kernel(semanage_handle_t *sh);
 int semanage_split_fc(semanage_handle_t *sh);
+int semanage_store_writable(semanage_handle_t *sh);
 
 #endif
diff -purN -x.svn libsemanage/src/semanageswig_wrap.c libsemanage/src/semanageswig_wrap.c
--- libsemanage/src/semanageswig_wrap.c	2006-01-20 11:30:59.000000000 -0500
+++ libsemanage/src/semanageswig_wrap.c	2006-01-20 11:42:19.000000000 -0500
@@ -2398,6 +2398,26 @@ static PyObject *_wrap_semanage_commit(P
 }
 
 
+static PyObject *_wrap_semanage_access_check(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
+    int result;
+    PyObject * obj0 = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"O:semanage_access_check",&obj0)) goto fail;
+    SWIG_Python_ConvertPtr(obj0, (void **)&arg1, SWIGTYPE_p_semanage_handle, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(1)) SWIG_fail;
+    result = (int)semanage_access_check(arg1);
+    
+    {
+        resultobj = SWIG_From_int((int)(result)); 
+    }
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyObject *_wrap_semanage_module_install(PyObject *self, PyObject *args) {
     PyObject *resultobj;
     semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
@@ -7472,6 +7492,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"semanage_disconnect", _wrap_semanage_disconnect, METH_VARARGS, NULL},
 	 { (char *)"semanage_begin_transaction", _wrap_semanage_begin_transaction, METH_VARARGS, NULL},
 	 { (char *)"semanage_commit", _wrap_semanage_commit, METH_VARARGS, NULL},
+	 { (char *)"semanage_access_check", _wrap_semanage_access_check, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install", _wrap_semanage_module_install, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_upgrade", _wrap_semanage_module_upgrade, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install_base", _wrap_semanage_module_install_base, METH_VARARGS, NULL},
@@ -8139,6 +8160,12 @@ SWIGEXPORT(void) SWIG_init(void) {
         PyDict_SetItemString(d,"SEMANAGE_CON_POLSERV_REMOTE", SWIG_From_int((int)(SEMANAGE_CON_POLSERV_REMOTE))); 
     }
     {
+        PyDict_SetItemString(d,"SEMANAGE_CAN_READ", SWIG_From_int((int)(1))); 
+    }
+    {
+        PyDict_SetItemString(d,"SEMANAGE_CAN_WRITE", SWIG_From_int((int)(2))); 
+    }
+    {
         PyDict_SetItemString(d,"SEMANAGE_PROTO_UDP", SWIG_From_int((int)(0))); 
     }
     {
diff -purN -x.svn policycoreutils/semanage/semanage policycoreutils/semanage/semanage
--- policycoreutils/semanage/semanage	2006-01-20 11:31:07.000000000 -0500
+++ policycoreutils/semanage/semanage	2006-01-20 11:37:33.000000000 -0500
@@ -24,9 +24,6 @@ import os, sys, getopt
 import seobject
 
 if __name__ == '__main__':
-	if os.getuid() > 0 or os.geteuid() > 0:
-		print "You must be root to run %s." % sys.argv[0]
-		sys.exit(0)
 
 	def usage(message = ""):
 		print '\
diff -purN -x.svn policycoreutils/semanage/seobject.py policycoreutils/semanage/seobject.py
--- policycoreutils/semanage/seobject.py	2006-01-20 11:31:07.000000000 -0500
+++ policycoreutils/semanage/seobject.py	2006-01-20 11:47:39.000000000 -0500
@@ -143,10 +143,19 @@ class semanageRecords:
 	def __init__(self):
 		self.sh = semanage_handle_create()
 		self.semanaged = semanage_is_managed(self.sh)
-		if self.semanaged:
-			rc = semanage_connect(self.sh)
-			if rc < 0:
-				raise ValueError("Could not establish semanage connection")
+		if not self.semanaged:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("SELinux policy is not managed.")
+
+		rc = semanage_access_check(self.sh)
+		if rc < SEMANAGE_CAN_READ:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Cannot read policy store.")
+
+		rc = semanage_connect(self.sh)
+		if rc < 0:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Could not establish semanage connection")
 
 class loginRecords(semanageRecords):
 	def __init__(self):

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 19:14   ` Joshua Brindle
@ 2006-01-20 20:49     ` Stephen Smalley
  2006-01-20 21:25       ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-20 20:49 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Fri, 2006-01-20 at 14:14 -0500, Joshua Brindle wrote:
> attached patch addresses all of the concerns with the prior patch. The
> main change is to make a function called semanage_access_check that
> returns error, existance, readable or writable. Depending on where the
> check is done test against one of them. 
> 
> I am now able to query the store as a non-root user after giving read
> access to /modules and /modules/active{,/*} and read/write to
> modules/semanage.read.LOCK
> 
> as expected I can query the store but not write to it, I also added a
> check for writability at the beginning of begin_transaction so that the
> user gets a nicer error when this happens.

Better, but a few lingering issues/questions:
1) Running semanage as a non-root user with existing default modes on
the policy module tree yields "SELinux policy is not managed."
So we aren't quite providing the right information to the user yet.

2) I'm still not sure about the check on the binary policy install
directory; not all "write" operations truly require rebuilding the
kernel binary policy, and we already have rollback code if that
installation fails, so I suspect that the writability check on the
active module store is good enough here.

3) I normally would have expected checking write access to the container
directory for the lock file rather than checking access to the lock file
itself, but I suppose since you create the lock file on the first
transaction and never remove it and use lockf for locking, it should
always exist if the store itself has been initialized?

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 20:49     ` Stephen Smalley
@ 2006-01-20 21:25       ` Joshua Brindle
  2006-01-23 14:36         ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-20 21:25 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Fri, 2006-01-20 at 14:14 -0500, Joshua Brindle wrote:
> 
>>attached patch addresses all of the concerns with the prior patch. The
>>main change is to make a function called semanage_access_check that
>>returns error, existance, readable or writable. Depending on where the
>>check is done test against one of them. 
>>
>>I am now able to query the store as a non-root user after giving read
>>access to /modules and /modules/active{,/*} and read/write to
>>modules/semanage.read.LOCK
>>
>>as expected I can query the store but not write to it, I also added a
>>check for writability at the beginning of begin_transaction so that the
>>user gets a nicer error when this happens.
> 
> 
> Better, but a few lingering issues/questions:
> 1) Running semanage as a non-root user with existing default modes on
> the policy module tree yields "SELinux policy is not managed."
> So we aren't quite providing the right information to the user yet.
>
if the user can't stat the module directory how do we know whether or 
not it is a managed system?


> 2) I'm still not sure about the check on the binary policy install
> directory; not all "write" operations truly require rebuilding the
> kernel binary policy, and we already have rollback code if that
> installation fails, so I suspect that the writability check on the
> active module store is good enough here.
> 
Only seuser doesn't require a policy rebuild, though I guess you could 
build in alternate stores without installing..

I guess that can be removed.

> 3) I normally would have expected checking write access to the container
> directory for the lock file rather than checking access to the lock file
> itself, but I suppose since you create the lock file on the first
> transaction and never remove it and use lockf for locking, it should
> always exist if the store itself has been initialized?
> 
the lock files are generally persistent, the current locking mechanism 
uses lockf instead of just testing for existence since lockf will 
release the lock on application exit.

I'd rather not give read only clients access to write to the module 
directory, even though it shouldn't matter as long as the active and 
previous directories are protected.

As far as querying goes read/write on the lock file is the absolute 
minimum required, so if that works they'll be able to query the store, 
which is what the access check should be checking. The only permission 
really needed to query the store could be lock but since the open call 
tries to create it if it doesn't exist, and also truncate then we have 
to allow read and write (also access doesn't have the ability to just 
test for lock)

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-20 21:25       ` Joshua Brindle
@ 2006-01-23 14:36         ` Stephen Smalley
  2006-01-23 14:51           ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-23 14:36 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Fri, 2006-01-20 at 16:25 -0500, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > Better, but a few lingering issues/questions:
> > 1) Running semanage as a non-root user with existing default modes on
> > the policy module tree yields "SELinux policy is not managed."
> > So we aren't quite providing the right information to the user yet.
> >
> if the user can't stat the module directory how do we know whether or 
> not it is a managed system?

Understood, but the message to the user needs to convey that fact, i.e.
instead of just saying "SELinux policy is not managed", we likely need
to say "SELinux policy is not managed or the module store is not
accessible to you."  

We also need to make sure that setsebool continues to do the right thing
here, as it uses semanage_is_managed() to decide whether it should a)
abort with an error (if < 0), b) fall back to the libselinux support for
setting booleans (== 0), or proceed to use the semanage functions for
setting booleans (> 0).  It looks like this patch is fine in that
respect since it doesn't change that interface; it should just silence
the warning we get from libsemanage in (b).  

Trying setsebool as a normal user I get "Could not change active
booleans:  Permission denied", which seems like a reasonable error
message for that case.  Only potential concern is that what is really
happening there is that setsebool is falling back to case (b) and trying
to directly manipulate booleans via libselinux, and it is only the lack
of permission to do so that prevents it from proceeding.  So if the
caller lacked permission to access the module store but had permission
to directly manipulate booleans (a pathological situation indeed), then
setsebool could do the wrong thing here.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 14:36         ` Stephen Smalley
@ 2006-01-23 14:51           ` Joshua Brindle
  2006-01-23 15:29             ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-23 14:51 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Fri, 2006-01-20 at 16:25 -0500, Joshua Brindle wrote:
> 
>>Stephen Smalley wrote:
>>
>>>Better, but a few lingering issues/questions:
>>>1) Running semanage as a non-root user with existing default modes on
>>>the policy module tree yields "SELinux policy is not managed."
>>>So we aren't quite providing the right information to the user yet.
>>>
>>
>>if the user can't stat the module directory how do we know whether or 
>>not it is a managed system?
> 
> 
> Understood, but the message to the user needs to convey that fact, i.e.
> instead of just saying "SELinux policy is not managed", we likely need
> to say "SELinux policy is not managed or the module store is not
> accessible to you."  

sounds good
> 
> We also need to make sure that setsebool continues to do the right thing
> here, as it uses semanage_is_managed() to decide whether it should a)
> abort with an error (if < 0), b) fall back to the libselinux support for
> setting booleans (== 0), or proceed to use the semanage functions for
> setting booleans (> 0).  It looks like this patch is fine in that
> respect since it doesn't change that interface; it should just silence
> the warning we get from libsemanage in (b).  
> 
yes, looking at setsebool it seems correct wrt is_managed. Which warning 
are you speaking of? In is_managed == 0 it uses 
selinux_set_boolean_list() and on success goes to out which destroys the 
handle and returns.

> Trying setsebool as a normal user I get "Could not change active
> booleans:  Permission denied", which seems like a reasonable error
> message for that case.  Only potential concern is that what is really
> happening there is that setsebool is falling back to case (b) and trying
> to directly manipulate booleans via libselinux, and it is only the lack
> of permission to do so that prevents it from proceeding.  So if the
> caller lacked permission to access the module store but had permission
> to directly manipulate booleans (a pathological situation indeed), then
> setsebool could do the wrong thing here.
> 

Hrm.. an interesting problem. How can we determine when the fallback 
should happen? It seems difficult to differenciate the 'not managed' and 
'no permission to see store' cases, which means setsebool can't know 
when to fallback and when not to. I'm not sure there is a solution to 
this problem except to encapsulate access to booleans through 
libsemanage clients, even in the targeted policy, which might not be 
acceptable.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 14:51           ` Joshua Brindle
@ 2006-01-23 15:29             ` Stephen Smalley
  2006-01-23 15:40               ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-23 15:29 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Mon, 2006-01-23 at 09:51 -0500, Joshua Brindle wrote:
> yes, looking at setsebool it seems correct wrt is_managed. Which warning 
> are you speaking of? In is_managed == 0 it uses 
> selinux_set_boolean_list() and on success goes to out which destroys the 
> handle and returns.

I just mean the old libsemanage warning from the old
is_managed()->create_store() code path, which is eliminated by your
patch.  That is a good thing, not a problem.

> Hrm.. an interesting problem. How can we determine when the fallback 
> should happen? It seems difficult to differenciate the 'not managed' and 
> 'no permission to see store' cases, which means setsebool can't know 
> when to fallback and when not to. I'm not sure there is a solution to 
> this problem except to encapsulate access to booleans through 
> libsemanage clients, even in the targeted policy, which might not be 
> acceptable.

I suspect it isn't a real issue in practice, but if we thought it was
truly crucial, we could introduce an explicit definition of is_managed
rather than inferring it from active module store existence, whether via
a definition in /etc/selinux/config or some other indicator (e.g. an
enable/disable flag in semanage.conf analogous to the one for
setrans.conf).

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 15:29             ` Stephen Smalley
@ 2006-01-23 15:40               ` Joshua Brindle
  2006-01-23 15:59                 ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-23 15:40 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Mon, 2006-01-23 at 09:51 -0500, Joshua Brindle wrote:
> 
>>yes, looking at setsebool it seems correct wrt is_managed. Which warning 
>>are you speaking of? In is_managed == 0 it uses 
>>selinux_set_boolean_list() and on success goes to out which destroys the 
>>handle and returns.
> 
> 
> I just mean the old libsemanage warning from the old
> is_managed()->create_store() code path, which is eliminated by your
> patch.  That is a good thing, not a problem.
> 
speaking of the create_store code path, That function is no longer in 
use and it was primarily used for bootstrapping non-managed systems so I 
didn't remove it yet but we can probably just require the package 
manager or make scripts to initialize the store and remove this from the 
library entirely.

> 
>>Hrm.. an interesting problem. How can we determine when the fallback 
>>should happen? It seems difficult to differenciate the 'not managed' and 
>>'no permission to see store' cases, which means setsebool can't know 
>>when to fallback and when not to. I'm not sure there is a solution to 
>>this problem except to encapsulate access to booleans through 
>>libsemanage clients, even in the targeted policy, which might not be 
>>acceptable.
> 
> 
> I suspect it isn't a real issue in practice, but if we thought it was
> truly crucial, we could introduce an explicit definition of is_managed
> rather than inferring it from active module store existence, whether via
> a definition in /etc/selinux/config or some other indicator (e.g. an
> enable/disable flag in semanage.conf analogous to the one for
> setrans.conf).
> 

I'd rather punt on that for now, in the case that it really matters 
(policy server) the store and boolean access will all be encapsulated 
and accessible only by the server.

Aside from the error string changes and the policy directory permission 
check removal does anything else need to be changed before resubmission? 
Should I go ahead and remove create_store?


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 15:40               ` Joshua Brindle
@ 2006-01-23 15:59                 ` Stephen Smalley
  2006-01-23 16:05                   ` Joshua Brindle
  2006-01-23 16:33                   ` Joshua Brindle
  0 siblings, 2 replies; 25+ messages in thread
From: Stephen Smalley @ 2006-01-23 15:59 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Mon, 2006-01-23 at 10:40 -0500, Joshua Brindle wrote:
> speaking of the create_store code path, That function is no longer in 
> use and it was primarily used for bootstrapping non-managed systems so I 
> didn't remove it yet but we can probably just require the package 
> manager or make scripts to initialize the store and remove this from the 
> library entirely.

Hmm...I missed that side effect.  Moving aside my module store and
trying to re-install the base module from /usr/share/selinux does indeed
fail against the new libsemanage (upon connect).  So the policy package
would have to pre-create the directory tree and the lock files so that
the connect could succeed?  I'm not sure that is truly what we want.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 15:59                 ` Stephen Smalley
@ 2006-01-23 16:05                   ` Joshua Brindle
  2006-01-23 16:18                     ` Stephen Smalley
  2006-01-23 16:33                   ` Joshua Brindle
  1 sibling, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-23 16:05 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Mon, 2006-01-23 at 10:40 -0500, Joshua Brindle wrote:
> 
>>speaking of the create_store code path, That function is no longer in 
>>use and it was primarily used for bootstrapping non-managed systems so I 
>>didn't remove it yet but we can probably just require the package 
>>manager or make scripts to initialize the store and remove this from the 
>>library entirely.
> 
> 
> Hmm...I missed that side effect.  Moving aside my module store and
> trying to re-install the base module from /usr/share/selinux does indeed
> fail against the new libsemanage (upon connect).  So the policy package
> would have to pre-create the directory tree and the lock files so that
> the connect could succeed?  I'm not sure that is truly what we want.
> 

before it was implicitly happening if it didn't exist (which will now 
result in an 'unmanaged system' return which should tell the client not 
call connect and therefore not initialize the store (i love bootstrap 
issues btw). I'm alright with making an explicit option to initialize it 
via semanage or semodule (preferably semodule).. would this be better?


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 16:05                   ` Joshua Brindle
@ 2006-01-23 16:18                     ` Stephen Smalley
  2006-01-26 20:40                       ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-23 16:18 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

On Mon, 2006-01-23 at 11:05 -0500, Joshua Brindle wrote:
> Stephen Smalley wrote:
> > On Mon, 2006-01-23 at 10:40 -0500, Joshua Brindle wrote:
> > 
> >>speaking of the create_store code path, That function is no longer in 
> >>use and it was primarily used for bootstrapping non-managed systems so I 
> >>didn't remove it yet but we can probably just require the package 
> >>manager or make scripts to initialize the store and remove this from the 
> >>library entirely.
> > 
> > 
> > Hmm...I missed that side effect.  Moving aside my module store and
> > trying to re-install the base module from /usr/share/selinux does indeed
> > fail against the new libsemanage (upon connect).  So the policy package
> > would have to pre-create the directory tree and the lock files so that
> > the connect could succeed?  I'm not sure that is truly what we want.
> > 
> 
> before it was implicitly happening if it didn't exist (which will now 
> result in an 'unmanaged system' return which should tell the client not 
> call connect and therefore not initialize the store (i love bootstrap 
> issues btw). I'm alright with making an explicit option to initialize it 
> via semanage or semodule (preferably semodule).. would this be better?

Why do we want changed behavior upon _connect at all?  Why not leave
connect alone (i.e. still call create_store(...,1) there), and just
change clients as desired to call access_check() when you don't want
such bootstrapping (which it seems is desirable as the default for
semodule -b)?

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 15:59                 ` Stephen Smalley
  2006-01-23 16:05                   ` Joshua Brindle
@ 2006-01-23 16:33                   ` Joshua Brindle
  1 sibling, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-01-23 16:33 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

Stephen Smalley wrote:
> On Mon, 2006-01-23 at 10:40 -0500, Joshua Brindle wrote:
> 
>>speaking of the create_store code path, That function is no longer in 
>>use and it was primarily used for bootstrapping non-managed systems so I 
>>didn't remove it yet but we can probably just require the package 
>>manager or make scripts to initialize the store and remove this from the 
>>library entirely.
> 
> 
> Hmm...I missed that side effect.  Moving aside my module store and
> trying to re-install the base module from /usr/share/selinux does indeed
> fail against the new libsemanage (upon connect).  So the policy package
> would have to pre-create the directory tree and the lock files so that
> the connect could succeed?  I'm not sure that is truly what we want.
> 

Mainly I changed it because if you didn't have write access it would 
spam the user with warnings and return -1. create_store is currently 
checking for R_OK | W_OK | X_OK access even if it is not necessary to 
make the directories. We could change this but that might have other 
side effects.

Further, since we don't know if the system is unmanaged or the modules 
directory is just inaccessible you can't even start a transaction right 
now (I added  if (semanage_access_check(sh) != SEMANAGE_CAN_WRITE) 
return -1 to direct_begintrans).

The main reason for this patch was to let the client give the user nice 
errors in these access cases since Dan's intention by checking for UID 
== 0 was to not spam the user with libsemanage debug messages. I'm not 
sure how to maintain the current behaviour while keeping access messages 
reasonably quiet.

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-23 16:18                     ` Stephen Smalley
@ 2006-01-26 20:40                       ` Joshua Brindle
  2006-01-27 15:12                         ` Stephen Smalley
  0 siblings, 1 reply; 25+ messages in thread
From: Joshua Brindle @ 2006-01-26 20:40 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Ivan Gyurdiev, SELinux List, selinuxdev

[-- Attachment #1: Type: text/plain, Size: 1940 bytes --]

On Mon, 2006-01-23 at 11:18 -0500, Stephen Smalley wrote:
> On Mon, 2006-01-23 at 11:05 -0500, Joshua Brindle wrote:
> > Stephen Smalley wrote:
> > > On Mon, 2006-01-23 at 10:40 -0500, Joshua Brindle wrote:
> > > 
> > >>speaking of the create_store code path, That function is no longer in 
> > >>use and it was primarily used for bootstrapping non-managed systems so I 
> > >>didn't remove it yet but we can probably just require the package 
> > >>manager or make scripts to initialize the store and remove this from the 
> > >>library entirely.
> > > 
> > > 
> > > Hmm...I missed that side effect.  Moving aside my module store and
> > > trying to re-install the base module from /usr/share/selinux does indeed
> > > fail against the new libsemanage (upon connect).  So the policy package
> > > would have to pre-create the directory tree and the lock files so that
> > > the connect could succeed?  I'm not sure that is truly what we want.
> > > 
> > 
> > before it was implicitly happening if it didn't exist (which will now 
> > result in an 'unmanaged system' return which should tell the client not 
> > call connect and therefore not initialize the store (i love bootstrap 
> > issues btw). I'm alright with making an explicit option to initialize it 
> > via semanage or semodule (preferably semodule).. would this be better?
> 
> Why do we want changed behavior upon _connect at all?  Why not leave
> connect alone (i.e. still call create_store(...,1) there), and just
> change clients as desired to call access_check() when you don't want
> such bootstrapping (which it seems is desirable as the default for
> semodule -b)?

This patch adds semanage_set_create_store which is callable by the
client to create the store. Set to 1 by semodule when called with -b.
Otherwise the same access checks as before are done.

Also adds semanage_is_connected to avoid an assertion failure in
semodule if an error occurs before connecting.

[-- Attachment #2: 1-semanage-write-check.diff --]
[-- Type: text/x-patch, Size: 16008 bytes --]

diff -x.svn -pruN libsemanage/include/semanage/handle.h libsemanage/include/semanage/handle.h
--- libsemanage/include/semanage/handle.h	2006-01-18 11:54:04.000000000 -0500
+++ libsemanage/include/semanage/handle.h	2006-01-26 15:35:51.000000000 -0500
@@ -64,6 +64,11 @@ void semanage_set_reload(semanage_handle
  * 1 for yes, 0 for no (default) */
 void semanage_set_rebuild(semanage_handle_t *handle, int do_rebuild);
 
+/* create the store if it does not exist, this only has an effect on 
+ * direct connections and must be called before semanage_connect 
+ * 1 for yes, 0 for no (default) */
+void semanage_set_create_store(semanage_handle_t *handle, int create_store);
+
 /* Check whether policy is managed via libsemanage on this system.
  * Must be called prior to trying to connect.
  * Return 1 if policy is managed via libsemanage on this system,
@@ -100,6 +105,15 @@ int semanage_begin_transaction(semanage_
  */
 int semanage_commit(semanage_handle_t *);
 
+#define SEMANAGE_CAN_READ 1
+#define SEMANAGE_CAN_WRITE 2
+/* returns SEMANAGE_CAN_READ or SEMANAGE_CAN_WRITE if the store is readable
+ * or writable, respectively. <0 if an error occured */ 
+int semanage_access_check(semanage_handle_t *sh);
+
+/* returns 0 if not connected, 1 if connected */
+int semanage_is_connected(semanage_handle_t *sh);
+
 /* META NOTES
  *
  * For all functions a non-negative number indicates success. For some
diff -x.svn -pruN libsemanage/src/direct_api.c libsemanage/src/direct_api.c
--- libsemanage/src/direct_api.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.c	2006-01-26 14:55:44.000000000 -0500
@@ -82,7 +82,7 @@ int semanage_direct_is_managed(semanage_
 	if (semanage_check_init(polpath))
 		goto err;
 
-	if (semanage_create_store(sh, 0) < 0) 
+	if (semanage_access_check(sh) < 0) 
 		return 0;
 
 	return 1;
@@ -102,7 +102,11 @@ int semanage_direct_connect(semanage_han
 	if (semanage_check_init(polpath))
 		goto err;
 
-	if (semanage_create_store(sh, 1) < 0) 
+	if (sh->create_store)
+		if (semanage_create_store(sh, 1))
+			goto err;
+
+	if (semanage_access_check(sh) < SEMANAGE_CAN_READ) 
 		goto err;
 
 	sh->u.direct.translock_file_fd = -1;
@@ -226,6 +230,10 @@ static int semanage_direct_disconnect(se
 }
 
 static int semanage_direct_begintrans(semanage_handle_t *sh) {
+	
+	if (semanage_access_check(sh) != SEMANAGE_CAN_WRITE) {
+		return -1;
+	}
 	if (semanage_get_trans_lock(sh) < 0) {
 		return -1;
 	}
@@ -775,3 +783,14 @@ static int semanage_direct_list(semanage
         }
 	return retval;
 }
+
+int semanage_direct_access_check(semanage_handle_t *sh) {
+	char polpath[PATH_MAX];	
+
+	snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), sh->conf->store_path);
+
+	if (semanage_check_init(polpath))
+		return -1;
+
+	return semanage_store_access_check(sh);
+}
diff -x.svn -pruN libsemanage/src/direct_api.h libsemanage/src/direct_api.h
--- libsemanage/src/direct_api.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/direct_api.h	2006-01-20 09:29:06.000000000 -0500
@@ -37,4 +37,6 @@ int semanage_direct_connect(
 int semanage_direct_is_managed(
 	struct semanage_handle *sh);
 
+int semanage_direct_access_check(struct semanage_handle *sh);
+
 #endif
diff -x.svn -pruN libsemanage/src/handle.c libsemanage/src/handle.c
--- libsemanage/src/handle.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle.c	2006-01-26 14:55:44.000000000 -0500
@@ -64,6 +64,9 @@ semanage_handle_t *semanage_handle_creat
 	/* By default always reload policy after commit if SELinux is enabled. */
 	sh->do_reload = (is_selinux_enabled() > 0);
 
+	/* By default do not create store */
+	sh->create_store = 0;
+
 	/* Set timeout: some default value for now, later use config */
 	sh->timeout = SEMANAGE_COMMIT_READ_WAIT; 
 
@@ -94,6 +97,19 @@ void semanage_set_reload(semanage_handle
 	return;
 }
 
+void semanage_set_create_store(semanage_handle_t *sh, int create_store) {
+	
+	assert(sh != NULL);
+
+	sh->create_store = create_store;
+	return;
+}
+
+int semanage_is_connected(semanage_handle_t *sh) {
+	assert(sh != NULL);
+	return sh->is_connected;
+}
+
 void semanage_select_store(semanage_handle_t *sh, char *storename,
 			  enum semanage_connect_type storetype) {
 	
@@ -142,6 +158,19 @@ int semanage_connect(semanage_handle_t *
 	return 0;
 }
 
+int semanage_access_check(semanage_handle_t *sh) {
+	assert(sh != NULL);
+	switch (sh->conf->store_type) {
+	case SEMANAGE_CON_DIRECT: 
+		return semanage_direct_access_check(sh);
+	default:
+		return -1;
+	}
+
+	return -1; /* unreachable */
+}
+hidden_def(semanage_access_check)
+
 int semanage_disconnect(semanage_handle_t *sh) {
 	assert(sh != NULL && sh->funcs != NULL && sh->funcs->disconnect != NULL);
 	if (!sh->is_connected) {
diff -x.svn -pruN libsemanage/src/handle.h libsemanage/src/handle.h
--- libsemanage/src/handle.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle.h	2006-01-26 14:55:44.000000000 -0500
@@ -63,6 +63,8 @@ struct semanage_handle {
 	int do_reload;		/* whether to reload policy after commit */
 	int do_rebuild;		/* whether to rebuild policy if there were no changes */
 	int modules_modified;
+	int create_store;	/* whether to create the store if it does not exist
+				 * this will only have an effect on direct connections */
 
 	/* This timeout is used for transactions and waiting for lock
 	   -1 means wait indefinetely
diff -x.svn -pruN libsemanage/src/handle_internal.h libsemanage/src/handle_internal.h
--- libsemanage/src/handle_internal.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/handle_internal.h	2006-01-20 09:29:19.000000000 -0500
@@ -7,5 +7,6 @@
 hidden_proto(semanage_begin_transaction)
 hidden_proto(semanage_handle_destroy)
 hidden_proto(semanage_reload_policy)
+hidden_proto(semanage_access_check)
 
 #endif
diff -x.svn -pruN libsemanage/src/libsemanage.map libsemanage/src/libsemanage.map
--- libsemanage/src/libsemanage.map	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/libsemanage.map	2006-01-26 14:55:44.000000000 -0500
@@ -11,6 +11,7 @@ LIBSEMANAGE_1.0 {
 	  semanage_reload_policy; semanage_set_reload; semanage_set_rebuild;
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
-	  semanage_fcontext_*;
+	  semanage_fcontext_*; semanage_access_check; semanage_set_create_store;
+	  semanage_is_connected;
   local: *;
 };
diff -x.svn -pruN libsemanage/src/semanage.py libsemanage/src/semanage.py
--- libsemanage/src/semanage.py	2006-01-20 11:30:59.000000000 -0500
+++ libsemanage/src/semanage.py	2006-01-20 11:42:19.000000000 -0500
@@ -87,6 +87,10 @@ semanage_disconnect = _semanage.semanage
 semanage_begin_transaction = _semanage.semanage_begin_transaction
 
 semanage_commit = _semanage.semanage_commit
+SEMANAGE_CAN_READ = _semanage.SEMANAGE_CAN_READ
+SEMANAGE_CAN_WRITE = _semanage.SEMANAGE_CAN_WRITE
+
+semanage_access_check = _semanage.semanage_access_check
 
 semanage_module_install = _semanage.semanage_module_install
 
diff -x.svn -pruN libsemanage/src/semanage_store.c libsemanage/src/semanage_store.c
--- libsemanage/src/semanage_store.c	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.c	2006-01-26 14:55:44.000000000 -0500
@@ -221,6 +221,8 @@ int semanage_create_store(semanage_handl
 	struct stat sb;
 	int mode_mask = R_OK | W_OK | X_OK;
 	const char *path = semanage_files[SEMANAGE_ROOT];
+	int fd;
+
 	if (stat(path, &sb) == -1) {
 		if (errno == ENOENT && create) {
 			if (mkdir(path, S_IRWXU) == -1) {
@@ -278,10 +280,76 @@ int semanage_create_store(semanage_handl
 			return -1;
 		}
 	}
+	path = semanage_files[SEMANAGE_READ_LOCK];
+	if (stat (path, &sb) == -1) {
+		if (errno == ENOENT && create) {
+			if ((fd = creat(path, S_IRUSR | S_IWUSR)) == -1) {
+				ERR(sh, "Could not create lock file at %s.", path);
+				return -2;
+			}
+		}
+		else {
+			ERR(sh, "Could not read lock file at %s.", path);
+			return -1;
+		}
+	}
+	else {
+		if (!S_ISREG(sb.st_mode) || access(path, R_OK | W_OK) == -1) {
+			ERR(sh, "Could not access lock file at %s.", path);
+			return -1;
+		}
+	}
 	return 0;
 }
 
+/* returns <0 if the active store cannot be read or doesn't exist
+ * 0 if the store exists but the lock file cannot be written to
+ * SEMANAGE_CAN_READ if the store can be read and the lock file written to
+ * SEMANAGE_CAN_WRITE if the modules directory and binary policy dir can be written to
+ */
+int semanage_store_access_check(semanage_handle_t *sh) {
+	const char *path;
+	char *path2, *path3;
+	int rc = -1;
+
+	/* read access on active store */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
+	if (access(path, R_OK | X_OK) != 0)
+		goto out;
+
+	/* we can read the active store meaning it is managed
+	 * so now we return 0 to indicate no error */
+	rc = 0;
+
+	/* read/write access on lock file required for reading */
+	path = semanage_files[SEMANAGE_READ_LOCK];
+	if (access(path, R_OK | W_OK) != 0)
+		goto out;
+
+	/* everything needed for reading has been checked */
+	rc = SEMANAGE_CAN_READ;
 
+	/* check the modules directory */
+	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
+	if (access(path, R_OK | W_OK | X_OK) != 0)
+		goto out;
+
+	/* check the binary policy install directory */
+	path = selinux_binary_policy_path();
+	path2 = strdup(path);
+	path3 = dirname(path2);
+
+	if ((access(path3, R_OK | W_OK | X_OK)) != 0) {
+		free(path2);
+		goto out;
+	}
+	free(path2);
+	
+	rc = SEMANAGE_CAN_WRITE;
+
+out:
+	return rc;
+}
 
 /********************* other I/O functions *********************/
 
diff -x.svn -pruN libsemanage/src/semanage_store.h libsemanage/src/semanage_store.h
--- libsemanage/src/semanage_store.h	2006-01-18 11:56:33.000000000 -0500
+++ libsemanage/src/semanage_store.h	2006-01-19 15:11:05.000000000 -0500
@@ -99,5 +99,6 @@ int semanage_verify_modules(
 int semanage_verify_linked(semanage_handle_t *sh);
 int semanage_verify_kernel(semanage_handle_t *sh);
 int semanage_split_fc(semanage_handle_t *sh);
+int semanage_store_writable(semanage_handle_t *sh);
 
 #endif
diff -x.svn -pruN libsemanage/src/semanageswig_wrap.c libsemanage/src/semanageswig_wrap.c
--- libsemanage/src/semanageswig_wrap.c	2006-01-20 11:30:59.000000000 -0500
+++ libsemanage/src/semanageswig_wrap.c	2006-01-20 11:42:19.000000000 -0500
@@ -2398,6 +2398,26 @@ static PyObject *_wrap_semanage_commit(P
 }
 
 
+static PyObject *_wrap_semanage_access_check(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
+    int result;
+    PyObject * obj0 = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"O:semanage_access_check",&obj0)) goto fail;
+    SWIG_Python_ConvertPtr(obj0, (void **)&arg1, SWIGTYPE_p_semanage_handle, SWIG_POINTER_EXCEPTION | 0);
+    if (SWIG_arg_fail(1)) SWIG_fail;
+    result = (int)semanage_access_check(arg1);
+    
+    {
+        resultobj = SWIG_From_int((int)(result)); 
+    }
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyObject *_wrap_semanage_module_install(PyObject *self, PyObject *args) {
     PyObject *resultobj;
     semanage_handle_t *arg1 = (semanage_handle_t *) 0 ;
@@ -7472,6 +7492,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"semanage_disconnect", _wrap_semanage_disconnect, METH_VARARGS, NULL},
 	 { (char *)"semanage_begin_transaction", _wrap_semanage_begin_transaction, METH_VARARGS, NULL},
 	 { (char *)"semanage_commit", _wrap_semanage_commit, METH_VARARGS, NULL},
+	 { (char *)"semanage_access_check", _wrap_semanage_access_check, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install", _wrap_semanage_module_install, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_upgrade", _wrap_semanage_module_upgrade, METH_VARARGS, NULL},
 	 { (char *)"semanage_module_install_base", _wrap_semanage_module_install_base, METH_VARARGS, NULL},
@@ -8139,6 +8160,12 @@ SWIGEXPORT(void) SWIG_init(void) {
         PyDict_SetItemString(d,"SEMANAGE_CON_POLSERV_REMOTE", SWIG_From_int((int)(SEMANAGE_CON_POLSERV_REMOTE))); 
     }
     {
+        PyDict_SetItemString(d,"SEMANAGE_CAN_READ", SWIG_From_int((int)(1))); 
+    }
+    {
+        PyDict_SetItemString(d,"SEMANAGE_CAN_WRITE", SWIG_From_int((int)(2))); 
+    }
+    {
         PyDict_SetItemString(d,"SEMANAGE_PROTO_UDP", SWIG_From_int((int)(0))); 
     }
     {
diff -x.svn -pruN policycoreutils/semanage/semanage policycoreutils/semanage/semanage
--- policycoreutils/semanage/semanage	2006-01-26 14:52:07.000000000 -0500
+++ policycoreutils/semanage/semanage	2006-01-26 14:54:10.000000000 -0500
@@ -24,9 +24,6 @@ import os, sys, getopt
 import seobject
 
 if __name__ == '__main__':
-	if os.getuid() > 0 or os.geteuid() > 0:
-		print "You must be root to run %s." % sys.argv[0]
-		sys.exit(0)
 
 	def usage(message = ""):
 		print '\
diff -x.svn -pruN policycoreutils/semanage/seobject.py policycoreutils/semanage/seobject.py
--- policycoreutils/semanage/seobject.py	2006-01-20 11:31:07.000000000 -0500
+++ policycoreutils/semanage/seobject.py	2006-01-26 15:11:45.000000000 -0500
@@ -143,10 +143,19 @@ class semanageRecords:
 	def __init__(self):
 		self.sh = semanage_handle_create()
 		self.semanaged = semanage_is_managed(self.sh)
-		if self.semanaged:
-			rc = semanage_connect(self.sh)
-			if rc < 0:
-				raise ValueError("Could not establish semanage connection")
+		if not self.semanaged:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("SELinux policy is not managed or store cannot be accessed.")
+
+		rc = semanage_access_check(self.sh)
+		if rc < SEMANAGE_CAN_READ:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Cannot read policy store.")
+
+		rc = semanage_connect(self.sh)
+		if rc < 0:
+			semanage_handle_destroy(self.sh)
+			raise ValueError("Could not establish semanage connection")
 
 class loginRecords(semanageRecords):
 	def __init__(self):
diff -x.svn -pruN policycoreutils/semodule/semodule.c policycoreutils/semodule/semodule.c
--- policycoreutils/semodule/semodule.c	2006-01-06 10:02:34.000000000 -0500
+++ policycoreutils/semodule/semodule.c	2006-01-26 15:11:45.000000000 -0500
@@ -41,6 +41,7 @@ static int num_commands = 0;
 static int verbose;
 static int reload;
 static int no_reload;
+static int create_store;
 static int build;
 
 static semanage_handle_t *sh = NULL;
@@ -169,9 +170,10 @@ static void parse_command_line(int argc,
         verbose = 0;
 	reload = 0;
 	no_reload = 0;
+	create_store = 0;
         while ((i = getopt_long(argc, argv, "s:b:hi:lvqr:u:RnB", opts, NULL)) != -1) {
                 switch (i) {
-                case 'b': set_mode(BASE_M, optarg); break;
+                case 'b': set_mode(BASE_M, optarg); create_store = 1; break;
                 case 'h': usage(argv[0]); exit(0);
                 case 'i': set_mode(INSTALL_M, optarg); break;
                 case 'l': set_mode(LIST_M, NULL); break;
@@ -233,6 +235,21 @@ int main(int argc, char *argv[]) {
 		 * location */
 		semanage_select_store(sh, store, SEMANAGE_CON_DIRECT);
 	}
+	
+	/* if installing base module create store if necessary, for bootstrapping */
+	semanage_set_create_store(sh, create_store);
+	
+	if (!create_store) {
+		if (!semanage_is_managed(sh)) {
+			fprintf(stderr, "%s: SELinux policy is not managed or store cannot be accessed.\n", argv[0]);
+			goto cleanup;
+		}
+	
+		if (semanage_access_check(sh) < SEMANAGE_CAN_READ) {
+			fprintf(stderr, "%s: Cannot read policy store.\n", argv[0]);
+			goto cleanup;
+		}
+	}
 
         if ((result = semanage_connect(sh)) < 0) {
                 fprintf(stderr, "%s:  Could not connect to policy handler\n", argv[0]);
@@ -359,9 +376,11 @@ int main(int argc, char *argv[]) {
         status = EXIT_SUCCESS;
 
  cleanup:
-        if (semanage_disconnect(sh) < 0) {
-		fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
-        }
+	if (semanage_is_connected(sh)) {
+	        if (semanage_disconnect(sh) < 0) {
+			fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
+		}
+	}
         semanage_handle_destroy(sh);
         cleanup();
         exit(status);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-26 20:40                       ` Joshua Brindle
@ 2006-01-27 15:12                         ` Stephen Smalley
  2006-01-27 15:17                           ` Joshua Brindle
  0 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2006-01-27 15:12 UTC (permalink / raw)
  To: Joshua Brindle; +Cc: Daniel J Walsh, Ivan Gyurdiev, SELinux List, selinuxdev

On Thu, 2006-01-26 at 15:40 -0500, Joshua Brindle wrote:
> This patch adds semanage_set_create_store which is callable by the
> client to create the store. Set to 1 by semodule when called with -b.
> Otherwise the same access checks as before are done.
> 
> Also adds semanage_is_connected to avoid an assertion failure in
> semodule if an error occurs before connecting.

Merged as of libsemanage 1.5.17 and policycoreutils 1.29.13, with the
following modifications:
- swigify/pywrap rebuild to pick up additional interfaces,
- dropped binary policy directory writability check,
- replaced obsolete semanage_store_writable prototype with
semanage_store_access_check prototype.

Also added a distclean target to the libsemanage top Makefile, and made
the relabel target apply restorecon to the .so file like the other
library Makefiles.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] libsemanage/semanage - permission check for semanage
  2006-01-27 15:12                         ` Stephen Smalley
@ 2006-01-27 15:17                           ` Joshua Brindle
  0 siblings, 0 replies; 25+ messages in thread
From: Joshua Brindle @ 2006-01-27 15:17 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: SELinux List

Stephen Smalley wrote:
> On Thu, 2006-01-26 at 15:40 -0500, Joshua Brindle wrote:
> 
>>This patch adds semanage_set_create_store which is callable by the
>>client to create the store. Set to 1 by semodule when called with -b.
>>Otherwise the same access checks as before are done.
>>
>>Also adds semanage_is_connected to avoid an assertion failure in
>>semodule if an error occurs before connecting.
> 
> 
> Merged as of libsemanage 1.5.17 and policycoreutils 1.29.13, with the
> following modifications:
> - swigify/pywrap rebuild to pick up additional interfaces,
> - dropped binary policy directory writability check,

ah, sorry, I meant to remove that

> - replaced obsolete semanage_store_writable prototype with
> semanage_store_access_check prototype.
>

> Also added a distclean target to the libsemanage top Makefile, and made
> the relabel target apply restorecon to the .so file like the other
> library Makefiles.
> 

Thanks

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2006-01-27 15:17 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-19 21:45 [PATCH] libsemanage/semanage - permission check for semanage Joshua Brindle
2006-01-19 22:45 ` Ivan Gyurdiev
2006-01-20  1:38   ` Joshua Brindle
2006-01-20  2:11     ` Ivan Gyurdiev
2006-01-20  2:19       ` Joshua Brindle
2006-01-20 13:54 ` Stephen Smalley
2006-01-20 14:00   ` Joshua Brindle
2006-01-20 14:24     ` Stephen Smalley
2006-01-20 14:09 ` Stephen Smalley
2006-01-20 14:04   ` Joshua Brindle
2006-01-20 15:20 ` Stephen Smalley
2006-01-20 19:14   ` Joshua Brindle
2006-01-20 20:49     ` Stephen Smalley
2006-01-20 21:25       ` Joshua Brindle
2006-01-23 14:36         ` Stephen Smalley
2006-01-23 14:51           ` Joshua Brindle
2006-01-23 15:29             ` Stephen Smalley
2006-01-23 15:40               ` Joshua Brindle
2006-01-23 15:59                 ` Stephen Smalley
2006-01-23 16:05                   ` Joshua Brindle
2006-01-23 16:18                     ` Stephen Smalley
2006-01-26 20:40                       ` Joshua Brindle
2006-01-27 15:12                         ` Stephen Smalley
2006-01-27 15:17                           ` Joshua Brindle
2006-01-23 16:33                   ` Joshua Brindle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.