We have a problem in the way we are handling booleans in FC3/RHEL4.
Basically we are allowing the user to edit the booleans
file either by hand or by using setsebool -P. One problem is that if we
want to override the default boolean value in policy with the booleans file.
We can not because selinux-policy-* has booleans marked as
config(noreplace). Otherwise the user would loose his settings. Second
problem is that setsebool allows users to customize booleans and as an
option make them permanent. The way it makes them pemanant is it takes
the values
that are currently running in the kernel and rewrites the boolean file.
This brings up the following bug
> setsebool allow_ypbind=0
> setsebool -P squid_disable_trans=1
Ends up with a booleans file containing
allow_ypbind=0
squid_disable_trans=1
Which is probably not what the user wanted.
So this patch changes the selinux handling of booleans. First it
introduces a new file booleans.local which will contain the users custom
boolean settings. booleans will be changes to a config file so that it
will be overwritten by rpm on upgrade. security_load_booleans now reads
booleans and booleans.local to setup boolean values. setsebool now only
writes the changed values to booleans.local.
Ideas?
Dan
--
diff --exclude-from=exclude -N -u -r nsalibselinux/include/selinux/selinux.h libselinux-1.23.2/include/selinux/selinux.h
--- nsalibselinux/include/selinux/selinux.h 2005-03-17 10:34:51.000000000 -0500
+++ libselinux-1.23.2/include/selinux/selinux.h 2005-03-24 09:39:12.000000000 -0500
@@ -136,6 +136,9 @@
/* Load a policy configuration. */
extern int security_load_policy(void *data, size_t len);
+/* Translate boolean strict to name value pair. */
+extern int security_process_boolean(char *buffer, char *name, int namelen, int *value);
+
/* Load policy boolean settings.
Path may be NULL, in which case the booleans are loaded from
the active policy boolean configuration file. */
diff --exclude-from=exclude -N -u -r nsalibselinux/src/booleans.c libselinux-1.23.2/src/booleans.c
--- nsalibselinux/src/booleans.c 2004-11-09 09:13:54.000000000 -0500
+++ libselinux-1.23.2/src/booleans.c 2005-03-24 09:39:12.000000000 -0500
@@ -238,51 +238,74 @@
dest[i+1]='\0';
return dest;
}
-
+int security_process_boolean(char *buffer, char *name, int namesize, int *val) {
+ char name1[BUFSIZ];
+ char *ptr;
+ char *tok=strtok_r(buffer,"=",&ptr);
+ if (tok) {
+ strncpy(name1,tok, BUFSIZ-1);
+ strtrim(name,name1,namesize-1);
+ if ( name[0]=='#' ) return 0;
+ tok=strtok_r(NULL,"\0",&ptr);
+ if (tok) {
+ while (isspace(*tok)) tok++;
+ *val = -1;
+ if (isdigit(tok[0]))
+ *val=atoi(tok);
+ else if (!strncmp(tok, "true", sizeof("true")-1))
+ *val = 1;
+ else if (!strncmp(tok, "false", sizeof("false")-1))
+ *val = 0;
+ if (*val != 0 && *val != 1) {
+ fprintf(stderr,"illegal value for boolean %s=%s\n", name, tok);
+ return -1;
+ }
+
+ }
+ }
+ return 1;
+}
int security_load_booleans(char *path) {
FILE *boolf;
char buffer[BUFSIZ];
- char name[BUFSIZ];
- char name1[BUFSIZ];
- int val;
+ char localbools[BUFSIZ];
int errors=0;
+ int val;
+ char name[BUFSIZ];
boolf = fopen(path ? path : selinux_booleans_path(),"r");
if (boolf == NULL)
return -1;
while (fgets_unlocked(buffer, sizeof(buffer), boolf)) {
- char *ptr;
- char *tok=strtok_r(buffer,"=",&ptr);
- if (tok) {
- strncpy(name1,tok, BUFSIZ-1);
- strtrim(name,name1,BUFSIZ-1);
- if ( name[0]=='#' ) continue;
- tok=strtok_r(NULL,"\0",&ptr);
- if (tok) {
- while (isspace(*tok)) tok++;
- val = -1;
- if (isdigit(tok[0]))
- val=atoi(tok);
- else if (!strncmp(tok, "true", sizeof("true")-1))
- val = 1;
- else if (!strncmp(tok, "false", sizeof("false")-1))
- val = 0;
- if (val != 0 && val != 1) {
- fprintf(stderr,"illegal value for boolean %s=%s\n", name, tok);
- errors++;
- continue;
- }
+ int ret=security_process_boolean(buffer, name, sizeof(name), &val);
+ if (ret==-1)
+ errors++;
+ if (ret==1)
+ if (security_set_boolean(name, val) < 0) {
+ fprintf(stderr,"error setting boolean %s to value %d \n", name, val);
+ errors++;
+ }
+ }
+ fclose(boolf);
+
+ snprintf(localbools,sizeof(localbools), "%s.local", (path ? path : selinux_booleans_path()));
+ boolf = fopen(localbools,"r");
+ if (boolf != NULL) {
+ int ret;
+ while (fgets_unlocked(buffer, sizeof(buffer), boolf)) {
+ ret=security_process_boolean(buffer, name, sizeof(name), &val);
+ if (ret==-1)
+ errors++;
+ if (ret==1)
if (security_set_boolean(name, val) < 0) {
fprintf(stderr,"error setting boolean %s to value %d \n", name, val);
errors++;
}
- }
}
+ fclose(boolf);
}
- fclose(boolf);
-
if (security_commit_booleans() < 0)
return -1;
diff --exclude-from=exclude -N -u -r nsalibselinux/utils/setsebool.c libselinux-1.23.2/utils/setsebool.c
--- nsalibselinux/utils/setsebool.c 2005-02-22 16:34:17.000000000 -0500
+++ libselinux-1.23.2/utils/setsebool.c 2005-03-24 10:38:20.000000000 -0500
@@ -76,8 +76,15 @@
{
char *name, *value_ptr;
int i=start, value;
+ int j=0;
+ int boolcnt=end-start;
struct passwd *pwd;
-
+ typedef struct {
+ char *name;
+ int value;
+ int used;
+ } boolean;
+ boolean *vallist=calloc(boolcnt, sizeof(boolean));
while (i < end) {
name = list[i];
value_ptr = strchr(list[i], '=');
@@ -110,7 +117,11 @@
rollback(list, start, i);
return 2;
}
+ vallist[j].value = value;
+ vallist[j].name = strdup(name);
+
i++;
+ j++;
/* Now put it back */
value_ptr--;
@@ -120,31 +131,17 @@
/* At this point we know that everything is good. Let's write
the file if the -P option was given. */
if (permanent) {
- char **names;
- const char *bool_file;
- char *tmp_bool_file;
- int rc, len, fd, j;
-
- rc = security_get_boolean_names(&names, &len);
- if (rc) {
- fprintf(stderr,
- "Unable to get boolean names: %s\n",
- strerror(errno));
- rollback(list, start, i);
- return 5;
- }
-
- if (!len) {
- fprintf(stderr,
- "Unable to get the boolean list from kernel - exiting\n"
- );
- rollback(list, start, i);
- return 6;
- }
-
+ int len;
+ char buffer[BUFSIZ];
+
/* Open file */
- bool_file = selinux_booleans_path();
- tmp_bool_file = (char *) alloca (strlen(bool_file) + 8);
+ const char *bool_file = selinux_booleans_path();
+ char *local_bool_file = (char *) alloca (strlen(bool_file) + 7);
+ char *tmp_bool_file = (char *) alloca (strlen(bool_file) + 8);
+ FILE *boolf;
+ int fd;
+ sprintf(local_bool_file, "%s.local", bool_file);
+ boolf = fopen(local_bool_file,"r");
strcpy(stpcpy(tmp_bool_file, bool_file), ".XXXXXX");
fd = mkstemp(tmp_bool_file);
if (fd < 0) {
@@ -152,35 +149,74 @@
"Error creating boolean file %s\n",
bool_file);
rollback(list, start, i);
+ for (i=0; i < boolcnt; i++)
+ free(vallist[i].name);
+ free(vallist);
return 7;
}
- /* Walk the list in pending memory, writing each to the file */
- for (j=0; j<len; j++) {
- char val_str[72];
- int len;
- int pending = security_get_boolean_pending(names[j]);
- len = snprintf(val_str, sizeof(val_str), "%s=%d\n",
- names[j], pending);
- if (write(fd, val_str, len) != len) {
- close_remove_fail:
- close(fd);
- remove_fail:
- unlink(tmp_bool_file);
- rollback(list, start, i);
- return 8;
+ if (boolf != NULL) {
+ int ret, val;
+ char boolname[BUFSIZ];
+ while (fgets_unlocked(buffer, sizeof(buffer), boolf)) {
+ ret=security_process_boolean(buffer, boolname, sizeof(boolname), &val);
+ if (ret!=1) {
+ len=strlen(buffer);
+ if (write(fd, buffer, len) != len)
+ goto close_remove_fail;
+ } else {
+ for (i=0; i < boolcnt; i++) {
+ if (strcmp(vallist[i].name, boolname)==0) {
+ snprintf(buffer,sizeof(buffer), "%s=%d\n", boolname, vallist[i].value);
+ len=strlen(buffer);
+ vallist[i].used=1;
+ if (write(fd, buffer, len) != len)
+ goto close_remove_fail;
+ else
+ break;
+ }
+ }
+ if ( i == boolcnt ) {
+ snprintf(buffer,sizeof(buffer), "%s=%d\n", boolname, val);
+ len=strlen(buffer);
+ if (write(fd, buffer, len) != len)
+ goto close_remove_fail;
+ }
+ }
}
+ fclose(boolf);
}
+ for (i=0; i < boolcnt; i++) {
+ if (vallist[i].used==0) {
+ snprintf(buffer,sizeof(buffer), "%s=%d\n", vallist[i].name, vallist[i].value);
+ len=strlen(buffer);
+ if (write(fd, buffer, len) != len) {
+ close_remove_fail:
+ close(fd);
+ remove_fail:
+ unlink(tmp_bool_file);
+ rollback(list, start, i);
+ for (i=0; i < boolcnt; i++)
+ free(vallist[i].name);
+ free(vallist);
+ return 8;
+ }
+ }
+
+ }
if (fchmod(fd, S_IRUSR | S_IWUSR) != 0)
goto close_remove_fail;
close(fd);
- if (rename(tmp_bool_file, bool_file) != 0)
+ if (rename(tmp_bool_file, local_bool_file) != 0)
goto remove_fail;
syslog(LOG_NOTICE, "%s has been updated.", bool_file);
}
-
+
+ for (i=0; i < boolcnt; i++)
+ free(vallist[i].name);
+ free(vallist);
/* OK, let's do the commit */
if (security_commit_booleans()) {
fputs("Error committing booleans\n", stderr);
--
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.
On Thu, 2005-03-24 at 13:21 -0500, Daniel J Walsh wrote:
> So this patch changes the selinux handling of booleans. First it
> introduces a new file booleans.local which will contain the users custom
> boolean settings. booleans will be changes to a config file so that it
> will be overwritten by rpm on upgrade. security_load_booleans now reads
> booleans and booleans.local to setup boolean values. setsebool now only
> writes the changed values to booleans.local.
Don't you need to modify libsepol (sepol_genbools) as well in order to
get booleans.local consulted by load_policy and /sbin/init?
--
Stephen Smalley <sds@epoch.ncsc.mil>
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.
Stephen Smalley wrote:
>On Thu, 2005-03-24 at 13:21 -0500, Daniel J Walsh wrote:
>
>
>>So this patch changes the selinux handling of booleans. First it
>>introduces a new file booleans.local which will contain the users custom
>>boolean settings. booleans will be changes to a config file so that it
>>will be overwritten by rpm on upgrade. security_load_booleans now reads
>>booleans and booleans.local to setup boolean values. setsebool now only
>>writes the changed values to booleans.local.
>>
>>
>
>Don't you need to modify libsepol (sepol_genbools) as well in order to
>get booleans.local consulted by load_policy and /sbin/init?
>
>
>
Ok here is the diff for sepol
--
diff --exclude-from=exclude -N -u -r nsalibsepol/src/genbools.c libsepol-1.5.2/src/genbools.c
--- nsalibsepol/src/genbools.c 2005-03-08 15:15:26.000000000 -0500
+++ libsepol-1.5.2/src/genbools.c 2005-03-24 13:43:55.000000000 -0500
@@ -24,11 +24,39 @@
return dest;
}
+static int process_boolean(char *buffer, char *name, int namesize, int *val) {
+ char name1[BUFSIZ];
+ char *ptr;
+ char *tok=strtok_r(buffer,"=",&ptr);
+ if (tok) {
+ strncpy(name1,tok, BUFSIZ-1);
+ strtrim(name,name1,namesize-1);
+ if ( name[0]=='#' ) return 0;
+ tok=strtok_r(NULL,"\0",&ptr);
+ if (tok) {
+ while (isspace(*tok)) tok++;
+ *val = -1;
+ if (isdigit(tok[0]))
+ *val=atoi(tok);
+ else if (!strncmp(tok, "true", sizeof("true")-1))
+ *val = 1;
+ else if (!strncmp(tok, "false", sizeof("false")-1))
+ *val = 0;
+ if (*val != 0 && *val != 1) {
+ fprintf(stderr,"illegal value for boolean %s=%s\n", name, tok);
+ return -1;
+ }
+
+ }
+ }
+ return 1;
+}
+
static int load_booleans(struct policydb *policydb, char *path) {
FILE *boolf;
char buffer[BUFSIZ];
+ char localbools[BUFSIZ];
char name[BUFSIZ];
- char name1[BUFSIZ];
int val;
int errors=0;
struct cond_bool_datum *datum;
@@ -38,27 +66,28 @@
return -1;
while (fgets(buffer, sizeof(buffer), boolf)) {
- char *tok=strtok(buffer,"=");
- if (tok) {
- strncpy(name1,tok, BUFSIZ-1);
- strtrim(name,name1,BUFSIZ-1);
- if ( name[0]=='#' ) continue;
- tok=strtok(NULL,"\0");
- if (tok) {
- while (isspace(*tok)) tok++;
- val = -1;
- if (isdigit(tok[0]))
- val=atoi(tok);
- else if (!strncasecmp(tok, "true", sizeof("true")-1))
- val = 1;
- else if (!strncasecmp(tok, "false", sizeof("false")-1))
- val = 0;
- if (val != 0 && val != 1) {
- fprintf(stderr,"illegal value for boolean %s=%s\n", name, tok);
- errors++;
- continue;
- }
-
+ int ret=process_boolean(buffer, name, sizeof(name), &val);
+ if (ret==-1)
+ errors++;
+ if (ret==1) {
+ datum = hashtab_search(policydb->p_bools.table, name);
+ if (!datum) {
+ fprintf(stderr,"unknown boolean %s\n", name);
+ errors++;
+ continue;
+ }
+ datum->state = val;
+ }
+ }
+ fclose(boolf);
+ snprintf(localbools,sizeof(localbools), "%s.local", path);
+ boolf = fopen(localbools,"r");
+ if (boolf != NULL) {
+ while (fgets(buffer, sizeof(buffer), boolf)) {
+ int ret=process_boolean(buffer, name, sizeof(name), &val);
+ if (ret==-1)
+ errors++;
+ if (ret==1) {
datum = hashtab_search(policydb->p_bools.table, name);
if (!datum) {
fprintf(stderr,"unknown boolean %s\n", name);
@@ -68,8 +97,8 @@
datum->state = val;
}
}
+ fclose(boolf);
}
- fclose(boolf);
if (errors)
errno = EINVAL;
--
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.