Home | History | Annotate | Download | only in src
      1 /*
      2  * Author: Karl MacMillan <kmacmillan (at) tresys.com>
      3  *
      4  * Modified:
      5  *   Dan Walsh <dwalsh (at) redhat.com> - Added security_load_booleans().
      6  */
      7 
      8 #include <sys/types.h>
      9 #include <sys/stat.h>
     10 #include <fcntl.h>
     11 #include <assert.h>
     12 #include <stdlib.h>
     13 #include <dirent.h>
     14 #include <string.h>
     15 #include <stdio.h>
     16 #include <unistd.h>
     17 #include <fnmatch.h>
     18 #include <limits.h>
     19 #include <ctype.h>
     20 #include <errno.h>
     21 
     22 #include "selinux_internal.h"
     23 #include "policy.h"
     24 
     25 #define SELINUX_BOOL_DIR "/booleans/"
     26 
     27 static int filename_select(const struct dirent *d)
     28 {
     29 	if (d->d_name[0] == '.'
     30 	    && (d->d_name[1] == '\0'
     31 		|| (d->d_name[1] == '.' && d->d_name[2] == '\0')))
     32 		return 0;
     33 	return 1;
     34 }
     35 
     36 int security_get_boolean_names(char ***names, int *len)
     37 {
     38 	char path[PATH_MAX];
     39 	int i, rc;
     40 	struct dirent **namelist;
     41 	char **n;
     42 
     43 	assert(len);
     44 	if (!selinux_mnt) {
     45 		errno = ENOENT;
     46 		return -1;
     47 	}
     48 
     49 	snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR);
     50 	*len = scandir(path, &namelist, &filename_select, alphasort);
     51 	if (*len <= 0) {
     52 		return -1;
     53 	}
     54 
     55 	n = (char **)malloc(sizeof(char *) * *len);
     56 	if (!n) {
     57 		rc = -1;
     58 		goto bad;
     59 	}
     60 
     61 	for (i = 0; i < *len; i++) {
     62 	        n[i] = strdup(namelist[i]->d_name);
     63 		if (!n[i]) {
     64 			rc = -1;
     65 			goto bad_freen;
     66 		}
     67 	}
     68 	rc = 0;
     69 	*names = n;
     70       out:
     71 	for (i = 0; i < *len; i++) {
     72 		free(namelist[i]);
     73 	}
     74 	free(namelist);
     75 	return rc;
     76       bad_freen:
     77 	for (--i; i >= 0; --i)
     78 		free(n[i]);
     79 	free(n);
     80       bad:
     81 	goto out;
     82 }
     83 
     84 hidden_def(security_get_boolean_names)
     85 #define STRBUF_SIZE 3
     86 static int get_bool_value(const char *name, char **buf)
     87 {
     88 	int fd, len;
     89 	char *fname = NULL;
     90 
     91 	if (!selinux_mnt) {
     92 		errno = ENOENT;
     93 		return -1;
     94 	}
     95 
     96 	*buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1));
     97 	if (!*buf)
     98 		goto out;
     99 	(*buf)[STRBUF_SIZE] = 0;
    100 
    101 	len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
    102 	fname = (char *)malloc(sizeof(char) * len);
    103 	if (!fname)
    104 		goto out;
    105 	snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
    106 
    107 	fd = open(fname, O_RDONLY);
    108 	if (fd < 0)
    109 		goto out;
    110 
    111 	len = read(fd, *buf, STRBUF_SIZE);
    112 	close(fd);
    113 	if (len != STRBUF_SIZE)
    114 		goto out;
    115 
    116 	free(fname);
    117 	return 0;
    118       out:
    119 	if (*buf)
    120 		free(*buf);
    121 	if (fname)
    122 		free(fname);
    123 	return -1;
    124 }
    125 
    126 int security_get_boolean_pending(const char *name)
    127 {
    128 	char *buf;
    129 	int val;
    130 
    131 	if (get_bool_value(name, &buf))
    132 		return -1;
    133 
    134 	if (atoi(&buf[1]))
    135 		val = 1;
    136 	else
    137 		val = 0;
    138 	free(buf);
    139 	return val;
    140 }
    141 
    142 int security_get_boolean_active(const char *name)
    143 {
    144 	char *buf;
    145 	int val;
    146 
    147 	if (get_bool_value(name, &buf))
    148 		return -1;
    149 
    150 	buf[1] = '\0';
    151 	if (atoi(buf))
    152 		val = 1;
    153 	else
    154 		val = 0;
    155 	free(buf);
    156 	return val;
    157 }
    158 
    159 hidden_def(security_get_boolean_active)
    160 
    161 int security_set_boolean(const char *name, int value)
    162 {
    163 	int fd, ret, len;
    164 	char buf[2], *fname;
    165 
    166 	if (!selinux_mnt) {
    167 		errno = ENOENT;
    168 		return -1;
    169 	}
    170 	if (value < 0 || value > 1) {
    171 		errno = EINVAL;
    172 		return -1;
    173 	}
    174 
    175 	len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
    176 	fname = (char *)malloc(sizeof(char) * len);
    177 	if (!fname)
    178 		return -1;
    179 	snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
    180 
    181 	fd = open(fname, O_WRONLY);
    182 	if (fd < 0) {
    183 		ret = -1;
    184 		goto out;
    185 	}
    186 
    187 	if (value)
    188 		buf[0] = '1';
    189 	else
    190 		buf[0] = '0';
    191 	buf[1] = '\0';
    192 
    193 	ret = write(fd, buf, 2);
    194 	close(fd);
    195       out:
    196 	free(fname);
    197 	if (ret > 0)
    198 		return 0;
    199 	else
    200 		return -1;
    201 }
    202 
    203 hidden_def(security_set_boolean)
    204 
    205 int security_commit_booleans(void)
    206 {
    207 	int fd, ret;
    208 	char buf[2];
    209 	char path[PATH_MAX];
    210 
    211 	if (!selinux_mnt) {
    212 		errno = ENOENT;
    213 		return -1;
    214 	}
    215 
    216 	snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt);
    217 	fd = open(path, O_WRONLY);
    218 	if (fd < 0)
    219 		return -1;
    220 
    221 	buf[0] = '1';
    222 	buf[1] = '\0';
    223 
    224 	ret = write(fd, buf, 2);
    225 	close(fd);
    226 
    227 	if (ret > 0)
    228 		return 0;
    229 	else
    230 		return -1;
    231 }
    232 
    233 hidden_def(security_commit_booleans)
    234 
    235 static void rollback(SELboolean * boollist, int end)
    236 {
    237 	int i;
    238 
    239 	for (i = 0; i < end; i++)
    240 		security_set_boolean(boollist[i].name,
    241 				     security_get_boolean_active(boollist[i].
    242 								 name));
    243 }
    244 
    245 int security_set_boolean_list(size_t boolcnt, SELboolean * const boollist,
    246 			      int permanent __attribute__((unused)))
    247 {
    248 
    249 	size_t i;
    250 	for (i = 0; i < boolcnt; i++) {
    251 		if (security_set_boolean(boollist[i].name, boollist[i].value)) {
    252 			rollback(boollist, i);
    253 			return -1;
    254 		}
    255 	}
    256 
    257 	/* OK, let's do the commit */
    258 	if (security_commit_booleans()) {
    259 		return -1;
    260 	}
    261 
    262 	return 0;
    263 }
    264