Example #1
0
int selinux_mkload_policy(int preservebools)
{	
	int kernvers = security_policyvers();
	int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers;
	int setlocaldefs = load_setlocaldefs;
	char path[PATH_MAX];
	struct stat sb;
	struct utsname uts;
	size_t size;
	void *map, *data;
	int fd, rc = -1, prot;
	sepol_policydb_t *policydb;
	sepol_policy_file_t *pf;
	int usesepol = 0;
	int (*vers_max)(void) = NULL;
	int (*vers_min)(void) = NULL;
	int (*policy_file_create)(sepol_policy_file_t **) = NULL;
	void (*policy_file_free)(sepol_policy_file_t *) = NULL;
	void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL;
	int (*policydb_create)(sepol_policydb_t **) = NULL;
	void (*policydb_free)(sepol_policydb_t *) = NULL;
	int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL;
	int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL;
	int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL;
	int (*genbools_array)(void *data, size_t len, char **names, int *values, int nel) = NULL;
	int (*genusers)(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) = NULL;
	int (*genbools)(void *data, size_t len, const char *boolpath) = NULL;

#ifdef SHARED
	char *errormsg = NULL;
	void *libsepolh = NULL;
	libsepolh = dlopen("libsepol.so.1", RTLD_NOW);
	if (libsepolh) {
		usesepol = 1;
		dlerror();
#define DLERR() if ((errormsg = dlerror())) goto dlclose;
		vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
		DLERR();
		vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
		DLERR();

		policy_file_create = dlsym(libsepolh, "sepol_policy_file_create");
		DLERR();
		policy_file_free = dlsym(libsepolh, "sepol_policy_file_free");
		DLERR();
		policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem");
		DLERR();
		policydb_create = dlsym(libsepolh, "sepol_policydb_create");
		DLERR();
		policydb_free = dlsym(libsepolh, "sepol_policydb_free");
		DLERR();
		policydb_read = dlsym(libsepolh, "sepol_policydb_read");
		DLERR();
		policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers");
		DLERR();
		policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image");
		DLERR();
		genbools_array = dlsym(libsepolh, "sepol_genbools_array");
		DLERR();
		genusers = dlsym(libsepolh, "sepol_genusers");
		DLERR();
		genbools = dlsym(libsepolh, "sepol_genbools");
		DLERR();

#undef DLERR
	}
#else
	usesepol = 1;
	vers_max = sepol_policy_kern_vers_max;
	vers_min = sepol_policy_kern_vers_min;
	policy_file_create = sepol_policy_file_create;
	policy_file_free = sepol_policy_file_free;
	policy_file_set_mem = sepol_policy_file_set_mem;
	policydb_create = sepol_policydb_create;
	policydb_free = sepol_policydb_free;
	policydb_read = sepol_policydb_read;
	policydb_set_vers = sepol_policydb_set_vers;
	policydb_to_image = sepol_policydb_to_image;
	genbools_array = sepol_genbools_array;
	genusers = sepol_genusers;
	genbools = sepol_genbools;

#endif

	/*
	 * Check whether we need to support local boolean and user definitions.
	 */
	if (setlocaldefs) {
		if (access(selinux_booleans_path(), F_OK) == 0)
			goto checkbool;
		snprintf(path, sizeof path, "%s.local", selinux_booleans_path());
		if (access(path, F_OK) == 0)
			goto checkbool;
		snprintf(path, sizeof path, "%s/local.users", selinux_users_path());
		if (access(path, F_OK) == 0)
			goto checkbool;
		/* No local definition files, so disable setlocaldefs. */
		setlocaldefs = 0;
	}

checkbool:
	/* 
	 * As of Linux 2.6.22, the kernel preserves boolean
	 * values across a reload, so we do not need to 
	 * preserve them in userspace.
	 */
	if (preservebools && uname(&uts) == 0 && strverscmp(uts.release, "2.6.22") >= 0)
		preservebools = 0;

	if (usesepol) {
		maxvers = vers_max();
		minvers = vers_min();
		if (!setlocaldefs && !preservebools)
			maxvers = max(kernvers, maxvers);
	}

	vers = maxvers;
      search:
	snprintf(path, sizeof(path), "%s.%d",
		 selinux_binary_policy_path(), vers);
	fd = open(path, O_RDONLY | O_CLOEXEC);
	while (fd < 0 && errno == ENOENT
	       && --vers >= minvers) {
		/* Check prior versions to see if old policy is available */
		snprintf(path, sizeof(path), "%s.%d",
			 selinux_binary_policy_path(), vers);
		fd = open(path, O_RDONLY | O_CLOEXEC);
	}
	if (fd < 0) {
		fprintf(stderr,
			"SELinux:  Could not open policy file <= %s.%d:  %s\n",
			selinux_binary_policy_path(), maxvers, strerror(errno));
		goto dlclose;
	}

	if (fstat(fd, &sb) < 0) {
		fprintf(stderr,
			"SELinux:  Could not stat policy file %s:  %s\n",
			path, strerror(errno));
		goto close;
	}

	prot = PROT_READ;
	if (setlocaldefs || preservebools)
		prot |= PROT_WRITE;

	size = sb.st_size;
	data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0);
	if (map == MAP_FAILED) {
		fprintf(stderr,
			"SELinux:  Could not map policy file %s:  %s\n",
			path, strerror(errno));
		goto close;
	}

	if (vers > kernvers && usesepol) {
		/* Need to downgrade to kernel-supported version. */
		if (policy_file_create(&pf))
			goto unmap;
		if (policydb_create(&policydb)) {
			policy_file_free(pf);
			goto unmap;
		}
		policy_file_set_mem(pf, data, size);
		if (policydb_read(policydb, pf)) {
			policy_file_free(pf);
			policydb_free(policydb);
			goto unmap;
		}
		if (policydb_set_vers(policydb, kernvers) ||
		    policydb_to_image(NULL, policydb, &data, &size)) {
			/* Downgrade failed, keep searching. */
			fprintf(stderr,
				"SELinux:  Could not downgrade policy file %s, searching for an older version.\n",
				path);
			policy_file_free(pf);
			policydb_free(policydb);
			munmap(map, sb.st_size);
			close(fd);
			vers--;
			goto search;
		}
		policy_file_free(pf);
		policydb_free(policydb);
	}

	if (usesepol) {
		if (setlocaldefs) {
			void *olddata = data;
			size_t oldsize = size;
			rc = genusers(olddata, oldsize, selinux_users_path(),
				      &data, &size);
			if (rc < 0) {
				/* Fall back to the prior image if genusers failed. */
				data = olddata;
				size = oldsize;
				rc = 0;
			} else {
				if (olddata != map)
					free(olddata);
			}
		}
		
		if (preservebools) {
			int *values, len, i;
			char **names;
			rc = security_get_boolean_names(&names, &len);
			if (!rc) {
				values = malloc(sizeof(int) * len);
				if (!values) {
					free(names);
					goto unmap;
				}
				for (i = 0; i < len; i++)
					values[i] =
						security_get_boolean_active(names[i]);
				(void)genbools_array(data, size, names, values,
						     len);
				free(values);
				for (i = 0; i < len; i++)
					free(names[i]);
				free(names);
			}
		} else if (setlocaldefs) {
			(void)genbools(data, size, selinux_booleans_path());
		}
	}


	rc = security_load_policy(data, size);
	
	if (rc)
		fprintf(stderr,
			"SELinux:  Could not load policy file %s:  %s\n",
			path, strerror(errno));

      unmap:
	if (data != map)
		free(data);
	munmap(map, sb.st_size);
      close:
	close(fd);
      dlclose:
#ifdef SHARED
	if (errormsg)
		fprintf(stderr, "libselinux:  %s\n", errormsg);
	if (libsepolh)
		dlclose(libsepolh);
#endif
	return rc;
}
Example #2
0
/* Compare S1 and S2 as strings holding indices/version numbers,
   returning less than, equal to or greater than zero if S1 is less than,
   equal to or greater than S2 (for more info, see the texinfo doc).
 */
int
str_verscmp (const char *s1, const char *s2)
{
#ifdef HAVE_STRVERSCMP
    return strverscmp (s1, s2);

#else /* HAVE_STRVERSCMP */
    unsigned char *p1 = (unsigned char *) s1;
    unsigned char *p2 = (unsigned char *) s2;
    unsigned char c1, c2;
    int state;
    int diff;

    /* Symbol(s)    0       [1-9]   others  (padding)
       Transition   (10) 0  (01) d  (00) x  (11) -   */
    static const unsigned int next_state[] = {
        /* state    x    d    0    - */
        /* S_N */ S_N, S_I, S_Z, S_N,
        /* S_I */ S_N, S_I, S_I, S_I,
        /* S_F */ S_N, S_F, S_F, S_F,
        /* S_Z */ S_N, S_F, S_Z, S_Z
    };

    static const int result_type[] = {
        /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
           0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */

        /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
        CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
        /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP,
        +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
        /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
        CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
        /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP,
        -1, CMP, CMP, CMP
    };

    if (p1 == p2)
        return 0;

    c1 = *p1++;
    c2 = *p2++;
    /* Hint: '0' is a digit too.  */
    state = S_N | ((c1 == '0') + (isdigit (c1) != 0));

    while ((diff = c1 - c2) == 0 && c1 != '\0')
    {
        state = next_state[state];
        c1 = *p1++;
        c2 = *p2++;
        state |= (c1 == '0') + (isdigit (c1) != 0);
    }

    state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))];

    switch (state)
    {
    case CMP:
        return diff;

    case LEN:
        while (isdigit (*p1++))
            if (!isdigit (*p2++))
                return 1;

        return isdigit (*p2) ? -1 : diff;

    default:
        return state;
    }
#endif /* HAVE_STRVERSCMP */
}
Example #3
0
static int
can_sigio(void)
{
  return strverscmp("2.6.37", uts.release) <= 0;
}
Example #4
0
static int version (const char **a, const char **b)
{
    return strverscmp (*a, *b);
}
/*
 * This is called once when selinux_restorecon() is first called.
 * Searches /proc/mounts for all file systems that do not support extended
 * attributes and adds them to the exclude directory table.  File systems
 * that support security labels have the seclabel option, return
 * approximate total file count.
 */
static int exclude_non_seclabel_mounts(void)
{
	struct utsname uts;
	FILE *fp;
	size_t len;
	ssize_t num;
	int index = 0, found = 0, nfile = 0;
	char *mount_info[4];
	char *buf = NULL, *item;

	/* Check to see if the kernel supports seclabel */
	if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0)
		return 0;
	if (is_selinux_enabled() <= 0)
		return 0;

	fp = fopen("/proc/mounts", "re");
	if (!fp)
		return 0;

	while ((num = getline(&buf, &len, fp)) != -1) {
		found = 0;
		index = 0;
		item = strtok(buf, " ");
		while (item != NULL) {
			mount_info[index] = item;
			index++;
			if (index == 4)
				break;
			item = strtok(NULL, " ");
		}
		if (index < 4) {
			selinux_log(SELINUX_ERROR,
				    "/proc/mounts record \"%s\" has incorrect format.\n",
				    buf);
			continue;
		}

		/* Remove pre-existing entry */
		remove_exclude(mount_info[1]);

		item = strtok(mount_info[3], ",");
		while (item != NULL) {
			if (strcmp(item, "seclabel") == 0) {
				found = 1;
				nfile += file_system_count(mount_info[1]);
				break;
			}
			item = strtok(NULL, ",");
		}

		/* Exclude mount points without the seclabel option */
		if (!found) {
			if (add_exclude(mount_info[1], !CALLER_EXCLUDED) &&
			    errno == ENOMEM)
				assert(0);
		}
	}

	free(buf);
	fclose(fp);
	/* return estimated #Files + 5% for directories and hard links */
	return nfile * 1.05;
}