Source file clang-analyzer cppcheck cpychecker gcc
policycoreutils-2.1.13/load_policy/load_policy.c 0 0 0 0
policycoreutils-2.1.13/newrole/hashtab.c 0 0 0 0
policycoreutils-2.1.13/newrole/newrole.c 0 1 0 0
policycoreutils-2.1.13/restorecond/restorecond.c 1 0 0 2
policycoreutils-2.1.13/restorecond/stringslist.c 1 0 0 0
policycoreutils-2.1.13/restorecond/user.c 0 0 0 0
policycoreutils-2.1.13/restorecond/utmpwatcher.c 0 0 0 0
policycoreutils-2.1.13/restorecond/watch.c 1 0 0 0
policycoreutils-2.1.13/run_init/open_init_pty.c 0 0 0 0
policycoreutils-2.1.13/run_init/run_init.c 0 0 0 0
policycoreutils-2.1.13/sandbox/seunshare.c 1 1 0 0
policycoreutils-2.1.13/secon/secon.c 0 0 0 0
policycoreutils-2.1.13/semanage/default_encoding/default_encoding.c 0 0 2 0
policycoreutils-2.1.13/semodule/semodule.c 0 0 0 0
policycoreutils-2.1.13/semodule_deps/semodule_deps.c 0 0 0 0
policycoreutils-2.1.13/semodule_expand/semodule_expand.c 0 0 0 0
policycoreutils-2.1.13/semodule_link/semodule_link.c 0 0 0 0
policycoreutils-2.1.13/semodule_package/semodule_package.c 0 0 0 0
policycoreutils-2.1.13/semodule_package/semodule_unpackage.c 0 0 0 0
policycoreutils-2.1.13/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c 0 0 0 0
policycoreutils-2.1.13/sepolicy/common.h 0 0 4 0
policycoreutils-2.1.13/sepolicy/info.c 0 0 4 0
policycoreutils-2.1.13/sepolicy/policy.c 0 0 1 0
policycoreutils-2.1.13/sepolicy/search.c 4 0 9 0
policycoreutils-2.1.13/sestatus/sestatus.c 0 0 0 0
policycoreutils-2.1.13/setfiles/restore.c 1 0 0 2
policycoreutils-2.1.13/setfiles/setfiles.c 0 0 0 0
policycoreutils-2.1.13/setsebool/setsebool.c 0 0 0 0

policycoreutils-2.1.13/load_policy/load_policy.c

No issues found

 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <errno.h>
 5 #include <getopt.h>
 6 #include <string.h>
 7 #include <selinux/selinux.h>
 8 #include <sepol/sepol.h>
 9 #ifdef USE_NLS
10 #include <locale.h>		/* for setlocale() */
11 #include <libintl.h>		/* for gettext() */
12 #define _(msgid) gettext (msgid)
13 #else
14 #define _(msgid) (msgid)
15 #endif
16 #ifndef PACKAGE
17 #define PACKAGE "policycoreutils"	/* the name of this package lang translation */
18 #endif
19 
20 void usage(char *progname)
21 {
22 	fprintf(stderr, _("usage:  %s [-qi]\n"), progname);
23 	exit(1);
24 }
25 
26 int main(int argc, char **argv)
27 {
28 	int ret, opt, quiet = 0, nargs, init=0, enforce=0;
29 
30 #ifdef USE_NLS
31 	setlocale(LC_ALL, "");
32 	bindtextdomain(PACKAGE, LOCALEDIR);
33 	textdomain(PACKAGE);
34 #endif
35 
36 	while ((opt = getopt(argc, argv, "bqi")) > 0) {
37 		switch (opt) {
38 		case 'b':
39 			fprintf(stderr, "%s:  Warning! The -b option is no longer supported, booleans are always preserved across reloads.  Continuing...\n",
40 				argv[0]);
41 			break;
42 		case 'q':
43 			quiet = 1;
44 			sepol_debug(0);
45 			break;
46 		case 'i':
47 			init = 1;
48 			break;
49 		default:
50 			usage(argv[0]);
51 		}
52 	}
53 
54 	nargs = argc - optind;
55 	if (nargs > 2)
56 		usage(argv[0]);
57 	if (nargs >= 1 && !quiet) {
58 			fprintf(stderr,
59 				"%s:  Warning!  Policy file argument (%s) is no longer supported, installed policy is always loaded.  Continuing...\n",
60 				argv[0], argv[optind++]);
61 	}
62 	if (nargs == 2 && ! quiet) {
63 		fprintf(stderr,
64 			"%s:  Warning!  Boolean file argument (%s) is no longer supported, installed booleans file is always used.  Continuing...\n",
65 			argv[0], argv[optind++]);
66 	}
67 	if (init) {
68 		if (is_selinux_enabled() == 1) {
69 			/* SELinux is already enabled, we should not do an initial load again */
70 			fprintf(stderr,
71 					_("%s:  Policy is already loaded and initial load requested\n"),
72 					argv[0]);
73 			exit(2);
74 		}
75 		ret = selinux_init_load_policy(&enforce);
76 		if (ret != 0 ) {
77 			if (enforce > 0) {
78 				/* SELinux in enforcing mode but load_policy failed */
79 				fprintf(stderr,
80 						_("%s:  Can't load policy and enforcing mode requested:  %s\n"),
81 						argv[0], strerror(errno));
82 				exit(3);
83 			}
84 		}
85 	}
86 	else {
87 		ret = selinux_mkload_policy(1);
88 	}
89 	if (ret < 0) {
90 		fprintf(stderr, _("%s:  Can't load policy:  %s\n"),
91 			argv[0], strerror(errno));
92 		exit(2);
93 	}
94 	exit(0);
95 }

policycoreutils-2.1.13/newrole/hashtab.c

No issues found

  1 /* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
  2 
  3 /* FLASK */
  4 
  5 /*
  6  * Implementation of the hash table type.
  7  */
  8 
  9 #include <stdlib.h>
 10 #include <string.h>
 11 #include "hashtab.h"
 12 
 13 hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
 14 						     const hashtab_key_t key),
 15 			 int (*keycmp) (hashtab_t h,
 16 					const hashtab_key_t key1,
 17 					const hashtab_key_t key2),
 18 			 unsigned int size)
 19 {
 20 
 21 	hashtab_t p;
 22 	unsigned int i;
 23 
 24 	p = (hashtab_t) malloc(sizeof(hashtab_val_t));
 25 	if (p == NULL)
 26 		return p;
 27 
 28 	memset(p, 0, sizeof(hashtab_val_t));
 29 	p->size = size;
 30 	p->nel = 0;
 31 	p->hash_value = hash_value;
 32 	p->keycmp = keycmp;
 33 	p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size);
 34 	if (p->htable == NULL) {
 35 		free(p);
 36 		return NULL;
 37 	}
 38 	for (i = 0; i < size; i++)
 39 		p->htable[i] = (hashtab_ptr_t) NULL;
 40 
 41 	return p;
 42 }
 43 
 44 int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
 45 {
 46 	int hvalue;
 47 	hashtab_ptr_t prev, cur, newnode;
 48 
 49 	if (!h)
 50 		return HASHTAB_OVERFLOW;
 51 
 52 	hvalue = h->hash_value(h, key);
 53 	prev = NULL;
 54 	cur = h->htable[hvalue];
 55 	while (cur && h->keycmp(h, key, cur->key) > 0) {
 56 		prev = cur;
 57 		cur = cur->next;
 58 	}
 59 
 60 	if (cur && (h->keycmp(h, key, cur->key) == 0))
 61 		return HASHTAB_PRESENT;
 62 
 63 	newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
 64 	if (newnode == NULL)
 65 		return HASHTAB_OVERFLOW;
 66 	memset(newnode, 0, sizeof(struct hashtab_node));
 67 	newnode->key = key;
 68 	newnode->datum = datum;
 69 	if (prev) {
 70 		newnode->next = prev->next;
 71 		prev->next = newnode;
 72 	} else {
 73 		newnode->next = h->htable[hvalue];
 74 		h->htable[hvalue] = newnode;
 75 	}
 76 
 77 	h->nel++;
 78 	return HASHTAB_SUCCESS;
 79 }
 80 
 81 int hashtab_remove(hashtab_t h, hashtab_key_t key,
 82 		   void (*destroy) (hashtab_key_t k,
 83 				    hashtab_datum_t d, void *args), void *args)
 84 {
 85 	int hvalue;
 86 	hashtab_ptr_t cur, last;
 87 
 88 	if (!h)
 89 		return HASHTAB_MISSING;
 90 
 91 	hvalue = h->hash_value(h, key);
 92 	last = NULL;
 93 	cur = h->htable[hvalue];
 94 	while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
 95 		last = cur;
 96 		cur = cur->next;
 97 	}
 98 
 99 	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
100 		return HASHTAB_MISSING;
101 
102 	if (last == NULL)
103 		h->htable[hvalue] = cur->next;
104 	else
105 		last->next = cur->next;
106 
107 	if (destroy)
108 		destroy(cur->key, cur->datum, args);
109 	free(cur);
110 	h->nel--;
111 	return HASHTAB_SUCCESS;
112 }
113 
114 int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum,
115 		    void (*destroy) (hashtab_key_t k,
116 				     hashtab_datum_t d, void *args), void *args)
117 {
118 	int hvalue;
119 	hashtab_ptr_t prev, cur, newnode;
120 
121 	if (!h)
122 		return HASHTAB_OVERFLOW;
123 
124 	hvalue = h->hash_value(h, key);
125 	prev = NULL;
126 	cur = h->htable[hvalue];
127 	while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
128 		prev = cur;
129 		cur = cur->next;
130 	}
131 
132 	if (cur && (h->keycmp(h, key, cur->key) == 0)) {
133 		if (destroy)
134 			destroy(cur->key, cur->datum, args);
135 		cur->key = key;
136 		cur->datum = datum;
137 	} else {
138 		newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
139 		if (newnode == NULL)
140 			return HASHTAB_OVERFLOW;
141 		memset(newnode, 0, sizeof(struct hashtab_node));
142 		newnode->key = key;
143 		newnode->datum = datum;
144 		if (prev) {
145 			newnode->next = prev->next;
146 			prev->next = newnode;
147 		} else {
148 			newnode->next = h->htable[hvalue];
149 			h->htable[hvalue] = newnode;
150 		}
151 	}
152 
153 	return HASHTAB_SUCCESS;
154 }
155 
156 hashtab_datum_t hashtab_search(hashtab_t h, const hashtab_key_t key)
157 {
158 
159 	int hvalue;
160 	hashtab_ptr_t cur;
161 
162 	if (!h)
163 		return NULL;
164 
165 	hvalue = h->hash_value(h, key);
166 	cur = h->htable[hvalue];
167 	while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
168 		cur = cur->next;
169 
170 	if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
171 		return NULL;
172 
173 	return cur->datum;
174 }
175 
176 void hashtab_destroy(hashtab_t h)
177 {
178 	unsigned int i;
179 	hashtab_ptr_t cur, temp;
180 
181 	if (!h)
182 		return;
183 
184 	for (i = 0; i < h->size; i++) {
185 		cur = h->htable[i];
186 		while (cur != NULL) {
187 			temp = cur;
188 			cur = cur->next;
189 			free(temp);
190 		}
191 		h->htable[i] = NULL;
192 	}
193 
194 	free(h->htable);
195 	h->htable = NULL;
196 
197 	free(h);
198 }
199 
200 int hashtab_map(hashtab_t h,
201 		int (*apply) (hashtab_key_t k,
202 			      hashtab_datum_t d, void *args), void *args)
203 {
204 	unsigned int i, ret;
205 	hashtab_ptr_t cur;
206 
207 	if (!h)
208 		return HASHTAB_SUCCESS;
209 
210 	for (i = 0; i < h->size; i++) {
211 		cur = h->htable[i];
212 		while (cur != NULL) {
213 			ret = apply(cur->key, cur->datum, args);
214 			if (ret)
215 				return ret;
216 			cur = cur->next;
217 		}
218 	}
219 	return HASHTAB_SUCCESS;
220 }
221 
222 void hashtab_map_remove_on_error(hashtab_t h,
223 				 int (*apply) (hashtab_key_t k,
224 					       hashtab_datum_t d,
225 					       void *args),
226 				 void (*destroy) (hashtab_key_t k,
227 						  hashtab_datum_t d,
228 						  void *args), void *args)
229 {
230 	unsigned int i;
231 	int ret;
232 	hashtab_ptr_t last, cur, temp;
233 
234 	if (!h)
235 		return;
236 
237 	for (i = 0; i < h->size; i++) {
238 		last = NULL;
239 		cur = h->htable[i];
240 		while (cur != NULL) {
241 			ret = apply(cur->key, cur->datum, args);
242 			if (ret) {
243 				if (last) {
244 					last->next = cur->next;
245 				} else {
246 					h->htable[i] = cur->next;
247 				}
248 
249 				temp = cur;
250 				cur = cur->next;
251 				if (destroy)
252 					destroy(temp->key, temp->datum, args);
253 				free(temp);
254 				h->nel--;
255 			} else {
256 				last = cur;
257 				cur = cur->next;
258 			}
259 		}
260 	}
261 
262 	return;
263 }
264 
265 void hashtab_hash_eval(hashtab_t h, char *tag)
266 {
267 	unsigned int i;
268 	int chain_len, slots_used, max_chain_len;
269 	hashtab_ptr_t cur;
270 
271 	slots_used = 0;
272 	max_chain_len = 0;
273 	for (i = 0; i < h->size; i++) {
274 		cur = h->htable[i];
275 		if (cur) {
276 			slots_used++;
277 			chain_len = 0;
278 			while (cur) {
279 				chain_len++;
280 				cur = cur->next;
281 			}
282 
283 			if (chain_len > max_chain_len)
284 				max_chain_len = chain_len;
285 		}
286 	}
287 
288 	printf
289 	    ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
290 	     tag, h->nel, slots_used, h->size, max_chain_len);
291 }

policycoreutils-2.1.13/newrole/newrole.c

Location Tool Test ID Issue
newrole.c:327:0 cppcheck useClosedFile Used file that is not opened.
   1 /************************************************************************
   2  *
   3  * newrole
   4  *
   5  * SYNOPSIS:
   6  *
   7  * This program allows a user to change their SELinux RBAC role and/or
   8  * SELinux TE type (domain) in a manner similar to the way the traditional
   9  * UNIX su program allows a user to change their identity.
  10  *
  11  * USAGE:
  12  *
  13  * newrole [ -r role ] [ -t type ] [ -l level ] [ -V ] [ -- args ]
  14  *
  15  * BUILD OPTIONS:
  16  *
  17  * option USE_PAM:
  18  *
  19  * Set the USE_PAM constant if you want to authenticate users via PAM.
  20  * If USE_PAM is not set, users will be authenticated via direct
  21  * access to the shadow password file.
  22  *
  23  * If you decide to use PAM must be told how to handle newrole.  A
  24  * good rule-of-thumb might be to tell PAM to handle newrole in the
  25  * same way it handles su, except that you should remove the pam_rootok.so
  26  * entry so that even root must re-authenticate to change roles. 
  27  *
  28  * If you choose not to use PAM, make sure you have a shadow passwd file
  29  * in /etc/shadow.  You can use a symlink if your shadow passwd file
  30  * lives in another directory.  Example:
  31  *   su
  32  *   cd /etc
  33  *   ln -s /etc/auth/shadow shadow
  34  *
  35  * If you decide not to use PAM, you will also have to make newrole
  36  * setuid root, so that it can read the shadow passwd file.
  37  * 
  38  *
  39  * Authors:
  40  *      Anthony Colatrella
  41  *	Tim Fraser
  42  *	Steve Grubb <sgrubb@redhat.com>
  43  *	Darrel Goeddel <DGoeddel@trustedcs.com>
  44  *	Michael Thompson <mcthomps@us.ibm.com>
  45  *	Dan Walsh <dwalsh@redhat.com>
  46  *
  47  *************************************************************************/
  48 
  49 #define _GNU_SOURCE
  50 
  51 #if defined(AUDIT_LOG_PRIV) && !defined(USE_AUDIT)
  52 #error AUDIT_LOG_PRIV needs the USE_AUDIT option
  53 #endif
  54 #if defined(NAMESPACE_PRIV) && !defined(USE_PAM)
  55 #error NAMESPACE_PRIV needs the USE_PAM option
  56 #endif
  57 
  58 #include <stdio.h>
  59 #include <stdlib.h>		/* for malloc(), realloc(), free() */
  60 #include <pwd.h>		/* for getpwuid() */
  61 #include <ctype.h>
  62 #include <sys/types.h>		/* to make getuid() and getpwuid() happy */
  63 #include <sys/wait.h>		/* for wait() */
  64 #include <getopt.h>		/* for getopt_long() form of getopt() */
  65 #include <fcntl.h>
  66 #include <string.h>
  67 #include <errno.h>
  68 #include <selinux/selinux.h>	/* for is_selinux_enabled() */
  69 #include <selinux/flask.h>	/* for SECCLASS_CHR_FILE */
  70 #include <selinux/context.h>	/* for context-mangling functions */
  71 #include <selinux/get_default_type.h>
  72 #include <selinux/get_context_list.h>	/* for SELINUX_DEFAULTUSER */
  73 #include <signal.h>
  74 #include <unistd.h>		/* for getuid(), exit(), getopt() */
  75 #ifdef USE_AUDIT
  76 #include <libaudit.h>
  77 #endif
  78 #if defined(AUDIT_LOG_PRIV) || (NAMESPACE_PRIV)
  79 #include <sys/prctl.h>
  80 #include <cap-ng.h>
  81 #endif
  82 #ifdef USE_NLS
  83 #include <locale.h>		/* for setlocale() */
  84 #include <libintl.h>		/* for gettext() */
  85 #define _(msgid) gettext (msgid)
  86 #else
  87 #define _(msgid) (msgid)
  88 #endif
  89 #ifndef PACKAGE
  90 #define PACKAGE "policycoreutils"	/* the name of this package lang translation */
  91 #endif
  92 
  93 #define TRUE 1
  94 #define FALSE 0
  95 
  96 /* USAGE_STRING describes the command-line args of this program. */
  97 #define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]"
  98 
  99 #ifdef USE_PAM
 100 #define PAM_SERVICE_CONFIG "/etc/selinux/newrole_pam.conf";
 101 #endif
 102 
 103 #define DEFAULT_PATH "/usr/bin:/bin"
 104 #define DEFAULT_CONTEXT_SIZE 255	/* first guess at context size */
 105 
 106 extern char **environ;
 107 
 108 /**
 109  * Construct from the current range and specified desired level a resulting
 110  * range. If the specified level is a range, return that. If it is not, then
 111  * construct a range with level as the sensitivity and clearance of the current
 112  * context.
 113  *
 114  * newlevel - the level specified on the command line
 115  * range    - the range in the current context
 116  *
 117  * Returns malloc'd memory
 118  */
 119 static char *build_new_range(char *newlevel, const char *range)
 120 {
 121 	char *newrangep = NULL;
 122 	const char *tmpptr;
 123 	size_t len;
 124 
 125 	/* a missing or empty string */
 126 	if (!range || !strlen(range) || !newlevel || !strlen(newlevel))
 127 		return NULL;
 128 
 129 	/* if the newlevel is actually a range - just use that */
 130 	if (strchr(newlevel, '-')) {
 131 		newrangep = strdup(newlevel);
 132 		return newrangep;
 133 	}
 134 
 135 	/* look for MLS range in current context */
 136 	tmpptr = strchr(range, '-');
 137 	if (tmpptr) {
 138 		/* we are inserting into a ranged MLS context */
 139 		len = strlen(newlevel) + 1 + strlen(tmpptr + 1) + 1;
 140 		newrangep = (char *)malloc(len);
 141 		if (!newrangep)
 142 			return NULL;
 143 		snprintf(newrangep, len, "%s-%s", newlevel, tmpptr + 1);
 144 	} else {
 145 		/* we are inserting into a currently non-ranged MLS context */
 146 		if (!strcmp(newlevel, range)) {
 147 			newrangep = strdup(range);
 148 		} else {
 149 			len = strlen(newlevel) + 1 + strlen(range) + 1;
 150 			newrangep = (char *)malloc(len);
 151 			if (!newrangep)
 152 				return NULL;
 153 			snprintf(newrangep, len, "%s-%s", newlevel, range);
 154 		}
 155 	}
 156 
 157 	return newrangep;
 158 }
 159 
 160 #ifdef USE_PAM
 161 
 162 /************************************************************************
 163  *
 164  * All PAM code goes in this section.
 165  *
 166  ************************************************************************/
 167 #include <security/pam_appl.h>	/* for PAM functions */
 168 #include <security/pam_misc.h>	/* for misc_conv PAM utility function */
 169 
 170 char *service_name = "newrole";
 171 
 172 /* authenticate_via_pam()
 173  *
 174  * in:     pw - struct containing data from our user's line in 
 175  *                         the passwd file.
 176  * out:    nothing
 177  * return: value   condition
 178  *         -----   ---------
 179  *           1     PAM thinks that the user authenticated themselves properly
 180  *           0     otherwise
 181  *
 182  * This function uses PAM to authenticate the user running this
 183  * program.  This is the only function in this program that makes PAM
 184  * calls.
 185  */
 186 int authenticate_via_pam(const char *ttyn, pam_handle_t * pam_handle)
 187 {
 188 
 189 	int result = 0;		/* set to 0 (not authenticated) by default */
 190 	int pam_rc;		/* pam return code */
 191 	const char *tty_name;
 192 
 193 	if (ttyn) {
 194 		if (strncmp(ttyn, "/dev/", 5) == 0)
 195 			tty_name = ttyn + 5;
 196 		else
 197 			tty_name = ttyn;
 198 
 199 		pam_rc = pam_set_item(pam_handle, PAM_TTY, tty_name);
 200 		if (pam_rc != PAM_SUCCESS) {
 201 			fprintf(stderr, _("failed to set PAM_TTY\n"));
 202 			goto out;
 203 		}
 204 	}
 205 
 206 	/* Ask PAM to authenticate the user running this program */
 207 	pam_rc = pam_authenticate(pam_handle, 0);
 208 	if (pam_rc != PAM_SUCCESS) {
 209 		goto out;
 210 	}
 211 
 212 	/* Ask PAM to verify acct_mgmt */
 213 	pam_rc = pam_acct_mgmt(pam_handle, 0);
 214 	if (pam_rc == PAM_SUCCESS) {
 215 		result = 1;	/* user authenticated OK! */
 216 	}
 217 
 218       out:
 219 	return result;
 220 }				/* authenticate_via_pam() */
 221 
 222 #include "hashtab.h"
 223 
 224 static int free_hashtab_entry(hashtab_key_t key, hashtab_datum_t d,
 225 			      void *args __attribute__ ((unused)))
 226 {
 227 	free(key);
 228 	free(d);
 229 	return 0;
 230 }
 231 
 232 static unsigned int reqsymhash(hashtab_t h, hashtab_key_t key)
 233 {
 234 	char *p, *keyp;
 235 	size_t size;
 236 	unsigned int val;
 237 
 238 	val = 0;
 239 	keyp = (char *)key;
 240 	size = strlen(keyp);
 241 	for (p = keyp; ((size_t) (p - keyp)) < size; p++)
 242 		val =
 243 		    (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
 244 	return val & (h->size - 1);
 245 }
 246 
 247 static int reqsymcmp(hashtab_t h
 248 		     __attribute__ ((unused)), hashtab_key_t key1,
 249 		     hashtab_key_t key2)
 250 {
 251 	char *keyp1, *keyp2;
 252 
 253 	keyp1 = (char *)key1;
 254 	keyp2 = (char *)key2;
 255 	return strcmp(keyp1, keyp2);
 256 }
 257 
 258 static hashtab_t app_service_names = NULL;
 259 #define PAM_SERVICE_SLOTS 64
 260 
 261 static int process_pam_config(FILE * cfg)
 262 {
 263 	const char *config_file_path = PAM_SERVICE_CONFIG;
 264 	char *line_buf = NULL;
 265 	unsigned long lineno = 0;
 266 	size_t len = 0;
 267 	char *app = NULL;
 268 	char *service = NULL;
 269 	int ret;
 270 
 271 	while (getline(&line_buf, &len, cfg) > 0) {
 272 		char *buffer = line_buf;
 273 		lineno++;
 274 		while (isspace(*buffer))
 275 			buffer++;
 276 		if (buffer[0] == '#')
 277 			continue;
 278 		if (buffer[0] == '\n' || buffer[0] == '\0')
 279 			continue;
 280 
 281 		app = service = NULL;
 282 		ret = sscanf(buffer, "%as %as\n", &app, &service);
 283 		if (ret < 2 || !app || !service)
 284 			goto err;
 285 
 286 		ret = hashtab_insert(app_service_names, app, service);
 287 		if (ret == HASHTAB_OVERFLOW) {
 288 			fprintf(stderr,
 289 				_
 290 				("newrole: service name configuration hashtable overflow\n"));
 291 			goto err;
 292 		}
 293 	}
 294 
 295 	free(line_buf);
 296 	return 0;
 297       err:
 298 	free(app);
 299 	free(service);
 300 	fprintf(stderr, _("newrole:  %s:  error on line %lu.\n"),
 301 		config_file_path, lineno);
 302 	free(line_buf);
 303 	return -1;
 304 }
 305 
 306 /* 
 307  *  Read config file ignoring comment lines.
 308  *  Files specified one per line executable with a corresponding
 309  *  pam service name.
 310  */
 311 static int read_pam_config()
 312 {
 313 	const char *config_file_path = PAM_SERVICE_CONFIG;
 314 	FILE *cfg = NULL;
 315 	cfg = fopen(config_file_path, "r");
 316 	if (!cfg)
 317 		return 0;	/* This configuration is optional. */
 318 	app_service_names =
 319 	    hashtab_create(reqsymhash, reqsymcmp, PAM_SERVICE_SLOTS);
 320 	if (!app_service_names)
 321 		goto err;
 322 	if (process_pam_config(cfg))
 323 		goto err;
 324 	fclose(cfg);
 325 	return 0;
 326       err:
 327 	fclose(cfg);
Used file that is not opened.
(emitted by cppcheck)
328 return -1; 329 } 330 331 #else /* else !USE_PAM */ 332 333 /************************************************************************ 334 * 335 * All shadow passwd code goes in this section. 336 * 337 ************************************************************************/ 338 #include <shadow.h> /* for shadow passwd functions */ 339 #include <string.h> /* for strlen(), memset() */ 340 341 #define PASSWORD_PROMPT _("Password:") /* prompt for getpass() */ 342 343 /* authenticate_via_shadow_passwd() 344 * 345 * in: uname - the calling user's user name 346 * out: nothing 347 * return: value condition 348 * ----- --------- 349 * 1 user authenticated themselves properly according to the 350 * shadow passwd file. 351 * 0 otherwise 352 * 353 * This function uses the shadow passwd file to thenticate the user running 354 * this program. 355 */ 356 int authenticate_via_shadow_passwd(const char *uname) 357 { 358 struct spwd *p_shadow_line; 359 char *unencrypted_password_s; 360 char *encrypted_password_s; 361 362 setspent(); 363 p_shadow_line = getspnam(uname); 364 endspent(); 365 if (!(p_shadow_line)) { 366 fprintf(stderr, _("Cannot find your entry in the shadow " 367 "passwd file.\n")); 368 return 0; 369 } 370 371 /* Ask user to input unencrypted password */ 372 if (!(unencrypted_password_s = getpass(PASSWORD_PROMPT))) { 373 fprintf(stderr, _("getpass cannot open /dev/tty\n")); 374 return 0; 375 } 376 377 /* Use crypt() to encrypt user's input password. */ 378 encrypted_password_s = crypt(unencrypted_password_s, 379 p_shadow_line->sp_pwdp); 380 memset(unencrypted_password_s, 0, strlen(unencrypted_password_s)); 381 return (!strcmp(encrypted_password_s, p_shadow_line->sp_pwdp)); 382 } 383 #endif /* if/else USE_PAM */ 384 385 /** 386 * This function checks to see if the shell is known in /etc/shells. 387 * If so, it returns 1. On error or illegal shell, it returns 0. 388 */ 389 static int verify_shell(const char *shell_name) 390 { 391 int found = 0; 392 const char *buf; 393 394 if (!(shell_name && shell_name[0])) 395 return found; 396 397 while ((buf = getusershell()) != NULL) { 398 /* ignore comments */ 399 if (*buf == '#') 400 continue; 401 402 /* check the shell skipping newline char */ 403 if (!strcmp(shell_name, buf)) { 404 found = 1; 405 break; 406 } 407 } 408 endusershell(); 409 return found; 410 } 411 412 /** 413 * Determine the Linux user identity to re-authenticate. 414 * If supported and set, use the login uid, as this should be more stable. 415 * Otherwise, use the real uid. 416 * 417 * This function assigns malloc'd memory into the pw_copy struct. 418 * Returns zero on success, non-zero otherwise 419 */ 420 int extract_pw_data(struct passwd *pw_copy) 421 { 422 uid_t uid; 423 struct passwd *pw; 424 425 #ifdef USE_AUDIT 426 uid = audit_getloginuid(); 427 if (uid == (uid_t) - 1) 428 uid = getuid(); 429 #else 430 uid = getuid(); 431 #endif 432 433 setpwent(); 434 pw = getpwuid(uid); 435 endpwent(); 436 if (!(pw && pw->pw_name && pw->pw_name[0] && pw->pw_shell 437 && pw->pw_shell[0] && pw->pw_dir && pw->pw_dir[0])) { 438 fprintf(stderr, 439 _("cannot find valid entry in the passwd file.\n")); 440 return -1; 441 } 442 443 *pw_copy = *pw; 444 pw = pw_copy; 445 pw->pw_name = strdup(pw->pw_name); 446 pw->pw_dir = strdup(pw->pw_dir); 447 pw->pw_shell = strdup(pw->pw_shell); 448 449 if (!(pw->pw_name && pw->pw_dir && pw->pw_shell)) { 450 fprintf(stderr, _("Out of memory!\n")); 451 goto out_free; 452 } 453 454 if (verify_shell(pw->pw_shell) == 0) { 455 fprintf(stderr, _("Error! Shell is not valid.\n")); 456 goto out_free; 457 } 458 return 0; 459 460 out_free: 461 free(pw->pw_name); 462 free(pw->pw_dir); 463 free(pw->pw_shell); 464 return -1; 465 } 466 467 /** 468 * Either restore the original environment, or set up a minimal one. 469 * 470 * The minimal environment contains: 471 * TERM, DISPLAY and XAUTHORITY - if they are set, preserve values 472 * HOME, SHELL, USER and LOGNAME - set to contents of /etc/passwd 473 * PATH - set to default value DEFAULT_PATH 474 * 475 * Returns zero on success, non-zero otherwise 476 */ 477 static int restore_environment(int preserve_environment, 478 char **old_environ, const struct passwd *pw) 479 { 480 char const *term_env; 481 char const *display_env; 482 char const *xauthority_env; 483 char *term = NULL; /* temporary container */ 484 char *display = NULL; /* temporary container */ 485 char *xauthority = NULL; /* temporary container */ 486 int rc; 487 488 environ = old_environ; 489 490 if (preserve_environment) 491 return 0; 492 493 term_env = getenv("TERM"); 494 display_env = getenv("DISPLAY"); 495 xauthority_env = getenv("XAUTHORITY"); 496 497 /* Save the variable values we want */ 498 if (term_env) 499 term = strdup(term_env); 500 if (display_env) 501 display = strdup(display_env); 502 if (xauthority_env) 503 xauthority = strdup(xauthority_env); 504 if ((term_env && !term) || (display_env && !display) || 505 (xauthority_env && !xauthority)) { 506 rc = -1; 507 goto out; 508 } 509 510 /* Construct a new environment */ 511 if ((rc = clearenv())) { 512 fprintf(stderr, _("Unable to clear environment\n")); 513 goto out; 514 } 515 516 /* Restore that which we saved */ 517 if (term) 518 rc |= setenv("TERM", term, 1); 519 if (display) 520 rc |= setenv("DISPLAY", display, 1); 521 if (xauthority) 522 rc |= setenv("XAUTHORITY", xauthority, 1); 523 rc |= setenv("HOME", pw->pw_dir, 1); 524 rc |= setenv("SHELL", pw->pw_shell, 1); 525 rc |= setenv("USER", pw->pw_name, 1); 526 rc |= setenv("LOGNAME", pw->pw_name, 1); 527 rc |= setenv("PATH", DEFAULT_PATH, 1); 528 out: 529 free(term); 530 free(display); 531 free(xauthority); 532 return rc; 533 } 534 535 /** 536 * This function will drop the capabilities so that we are left 537 * only with access to the audit system. If the user is root, we leave 538 * the capabilities alone since they already should have access to the 539 * audit netlink socket. 540 * 541 * Returns zero on success, non-zero otherwise 542 */ 543 #if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV) 544 static int drop_capabilities(int full) 545 { 546 uid_t uid = getuid(); 547 if (!uid) return 0; 548 549 capng_setpid(getpid()); 550 capng_clear(CAPNG_SELECT_BOTH); 551 if (capng_lock() < 0) 552 return -1; 553 554 /* Change uid */ 555 if (setresuid(uid, uid, uid)) { 556 fprintf(stderr, _("Error changing uid, aborting.\n")); 557 return -1; 558 } 559 if (! full) 560 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_AUDIT_WRITE); 561 return capng_apply(CAPNG_SELECT_BOTH); 562 } 563 #elif defined(NAMESPACE_PRIV) 564 /** 565 * This function will drop the capabilities so that we are left 566 * only with access to the audit system and the ability to raise 567 * CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_FOWNER and CAP_CHOWN, 568 * before invoking pam_namespace. These capabilities are needed 569 * for performing bind mounts/unmounts and to create potential new 570 * instance directories with appropriate DAC attributes. If the 571 * user is root, we leave the capabilities alone since they already 572 * should have access to the audit netlink socket and should have 573 * the ability to create/mount/unmount instance directories. 574 * 575 * Returns zero on success, non-zero otherwise 576 */ 577 static int drop_capabilities(int full) 578 { 579 capng_setpid(getpid()); 580 capng_clear(CAPNG_SELECT_BOTH); 581 if (capng_lock() < 0) 582 return -1; 583 584 uid_t uid = getuid(); 585 /* Change uid */ 586 if (setresuid(uid, uid, uid)) { 587 fprintf(stderr, _("Error changing uid, aborting.\n")); 588 return -1; 589 } 590 if (! full) 591 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_SYS_ADMIN , CAP_FOWNER , CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_SETPCAP, -1); 592 return capng_apply(CAPNG_SELECT_BOTH); 593 } 594 595 #else 596 static inline int drop_capabilities(__attribute__ ((__unused__)) int full) 597 { 598 return 0; 599 } 600 #endif 601 602 #ifdef NAMESPACE_PRIV 603 /** 604 * This function will set the uid values to be that of caller's uid, and 605 * will drop any privilages which maybe have been raised. 606 */ 607 static int transition_to_caller_uid() 608 { 609 uid_t uid = getuid(); 610 611 if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) { 612 fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); 613 return -1; 614 } 615 616 if (setresuid(uid, uid, uid)) { 617 fprintf(stderr, _("Error changing uid, aborting.\n")); 618 return -1; 619 } 620 return 0; 621 } 622 #endif 623 624 #ifdef AUDIT_LOG_PRIV 625 /* Send audit message */ 626 static 627 int send_audit_message(int success, security_context_t old_context, 628 security_context_t new_context, const char *ttyn) 629 { 630 char *msg = NULL; 631 int rc; 632 int audit_fd = audit_open(); 633 634 if (audit_fd < 0) { 635 fprintf(stderr, _("Error connecting to audit system.\n")); 636 return -1; 637 } 638 if (asprintf(&msg, "newrole: old-context=%s new-context=%s", 639 old_context ? old_context : "?", 640 new_context ? new_context : "?") < 0) { 641 fprintf(stderr, _("Error allocating memory.\n")); 642 rc = -1; 643 goto out; 644 } 645 rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, 646 msg, NULL, NULL, ttyn, success); 647 if (rc <= 0) { 648 fprintf(stderr, _("Error sending audit message.\n")); 649 rc = -1; 650 goto out; 651 } 652 rc = 0; 653 out: 654 free(msg); 655 close(audit_fd); 656 return rc; 657 } 658 #else 659 static inline 660 int send_audit_message(int success __attribute__ ((unused)), 661 security_context_t old_context 662 __attribute__ ((unused)), 663 security_context_t new_context 664 __attribute__ ((unused)), const char *ttyn 665 __attribute__ ((unused))) 666 { 667 return 0; 668 } 669 #endif 670 671 /** 672 * This function attempts to relabel the tty. If this function fails, then 673 * the fd is closed, the contexts are free'd and -1 is returned. On success, 674 * a valid fd is returned and tty_context and new_tty_context are set. 675 * 676 * This function will not fail if it can not relabel the tty when selinux is 677 * in permissive mode. 678 */ 679 static int relabel_tty(const char *ttyn, security_context_t new_context, 680 security_context_t * tty_context, 681 security_context_t * new_tty_context) 682 { 683 int fd; 684 int enforcing = security_getenforce(); 685 security_context_t tty_con = NULL; 686 security_context_t new_tty_con = NULL; 687 688 if (!ttyn) 689 return 0; 690 691 if (enforcing < 0) { 692 fprintf(stderr, _("Could not determine enforcing mode.\n")); 693 return -1; 694 } 695 696 /* Re-open TTY descriptor */ 697 fd = open(ttyn, O_RDWR | O_NONBLOCK); 698 if (fd < 0) { 699 fprintf(stderr, _("Error! Could not open %s.\n"), ttyn); 700 return fd; 701 } 702 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); 703 704 if (fgetfilecon(fd, &tty_con) < 0) { 705 fprintf(stderr, _("%s! Could not get current context " 706 "for %s, not relabeling tty.\n"), 707 enforcing ? "Error" : "Warning", ttyn); 708 if (enforcing) 709 goto close_fd; 710 } 711 712 if (tty_con && 713 (security_compute_relabel(new_context, tty_con, 714 SECCLASS_CHR_FILE, &new_tty_con) < 0)) { 715 fprintf(stderr, _("%s! Could not get new context for %s, " 716 "not relabeling tty.\n"), 717 enforcing ? "Error" : "Warning", ttyn); 718 if (enforcing) 719 goto close_fd; 720 } 721 722 if (new_tty_con) 723 if (fsetfilecon(fd, new_tty_con) < 0) { 724 fprintf(stderr, 725 _("%s! Could not set new context for %s\n"), 726 enforcing ? "Error" : "Warning", ttyn); 727 freecon(new_tty_con); 728 new_tty_con = NULL; 729 if (enforcing) 730 goto close_fd; 731 } 732 733 *tty_context = tty_con; 734 *new_tty_context = new_tty_con; 735 return fd; 736 737 close_fd: 738 freecon(tty_con); 739 close(fd); 740 return -1; 741 } 742 743 /** 744 * This function attempts to revert the relabeling done to the tty. 745 * fd - referencing the opened ttyn 746 * ttyn - name of tty to restore 747 * tty_context - original context of the tty 748 * new_tty_context - context tty was relabeled to 749 * 750 * Returns zero on success, non-zero otherwise 751 */ 752 static int restore_tty_label(int fd, const char *ttyn, 753 security_context_t tty_context, 754 security_context_t new_tty_context) 755 { 756 int rc = 0; 757 security_context_t chk_tty_context = NULL; 758 759 if (!ttyn) 760 goto skip_relabel; 761 762 if (!new_tty_context) 763 goto skip_relabel; 764 765 /* Verify that the tty still has the context set by newrole. */ 766 if ((rc = fgetfilecon(fd, &chk_tty_context)) < 0) { 767 fprintf(stderr, "Could not fgetfilecon %s.\n", ttyn); 768 goto skip_relabel; 769 } 770 771 if ((rc = strcmp(chk_tty_context, new_tty_context))) { 772 fprintf(stderr, _("%s changed labels.\n"), ttyn); 773 goto skip_relabel; 774 } 775 776 if ((rc = fsetfilecon(fd, tty_context)) < 0) 777 fprintf(stderr, 778 _("Warning! Could not restore context for %s\n"), ttyn); 779 skip_relabel: 780 freecon(chk_tty_context); 781 return rc; 782 } 783 784 /** 785 * Parses and validates the provided command line options and 786 * constructs a new context based on our old context and the 787 * arguments specified on the command line. On success 788 * new_context will be set to valid values, otherwise its value 789 * is left unchanged. 790 * 791 * Returns zero on success, non-zero otherwise. 792 */ 793 static int parse_command_line_arguments(int argc, char **argv, char *ttyn, 794 security_context_t old_context, 795 security_context_t * new_context, 796 int *preserve_environment) 797 { 798 int flag_index; /* flag index in argv[] */ 799 int clflag; /* holds codes for command line flags */ 800 char *role_s = NULL; /* role spec'd by user in argv[] */ 801 char *type_s = NULL; /* type spec'd by user in argv[] */ 802 char *type_ptr = NULL; /* stores malloc'd data from get_default_type */ 803 char *level_s = NULL; /* level spec'd by user in argv[] */ 804 char *range_ptr = NULL; 805 security_context_t new_con = NULL; 806 security_context_t tty_con = NULL; 807 context_t context = NULL; /* manipulatable form of new_context */ 808 const struct option long_options[] = { 809 {"role", 1, 0, 'r'}, 810 {"type", 1, 0, 't'}, 811 {"level", 1, 0, 'l'}, 812 {"preserve-environment", 0, 0, 'p'}, 813 {"version", 0, 0, 'V'}, 814 {NULL, 0, 0, 0} 815 }; 816 817 *preserve_environment = 0; 818 while (1) { 819 clflag = getopt_long(argc, argv, "r:t:l:pV", long_options, 820 &flag_index); 821 if (clflag == -1) 822 break; 823 824 switch (clflag) { 825 case 'V': 826 printf("newrole: %s version %s\n", PACKAGE, VERSION); 827 exit(0); 828 break; 829 case 'p': 830 *preserve_environment = 1; 831 break; 832 case 'r': 833 if (role_s) { 834 fprintf(stderr, 835 _("Error: multiple roles specified\n")); 836 return -1; 837 } 838 role_s = optarg; 839 break; 840 case 't': 841 if (type_s) { 842 fprintf(stderr, 843 _("Error: multiple types specified\n")); 844 return -1; 845 } 846 type_s = optarg; 847 break; 848 case 'l': 849 if (!is_selinux_mls_enabled()) { 850 fprintf(stderr, _("Sorry, -l may be used with " 851 "SELinux MLS support.\n")); 852 return -1; 853 } 854 if (level_s) { 855 fprintf(stderr, _("Error: multiple levels " 856 "specified\n")); 857 return -1; 858 } 859 if (ttyn) { 860 if (fgetfilecon(STDIN_FILENO, &tty_con) >= 0) { 861 if (selinux_check_securetty_context 862 (tty_con) < 0) { 863 fprintf(stderr, 864 _ 865 ("Error: you are not allowed to change levels on a non secure terminal \n")); 866 freecon(tty_con); 867 return -1; 868 } 869 freecon(tty_con); 870 } 871 } 872 873 level_s = optarg; 874 break; 875 default: 876 fprintf(stderr, "%s\n", USAGE_STRING); 877 return -1; 878 } 879 } 880 881 /* Verify that the combination of command-line arguments are viable */ 882 if (!(role_s || type_s || level_s)) { 883 fprintf(stderr, "%s\n", USAGE_STRING); 884 return -1; 885 } 886 887 /* Fill in a default type if one hasn't been specified. */ 888 if (role_s && !type_s) { 889 /* get_default_type() returns malloc'd memory */ 890 if (get_default_type(role_s, &type_ptr)) { 891 fprintf(stderr, _("Couldn't get default type.\n")); 892 send_audit_message(0, old_context, new_con, ttyn); 893 return -1; 894 } 895 type_s = type_ptr; 896 } 897 898 /* Create a temporary new context structure we extract and modify */ 899 context = context_new(old_context); 900 if (!context) { 901 fprintf(stderr, _("failed to get new context.\n")); 902 goto err_free; 903 } 904 905 /* Modify the temporary new context */ 906 if (role_s) 907 if (context_role_set(context, role_s)) { 908 fprintf(stderr, _("failed to set new role %s\n"), 909 role_s); 910 goto err_free; 911 } 912 913 if (type_s) 914 if (context_type_set(context, type_s)) { 915 fprintf(stderr, _("failed to set new type %s\n"), 916 type_s); 917 goto err_free; 918 } 919 920 if (level_s) { 921 range_ptr = 922 build_new_range(level_s, context_range_get(context)); 923 if (!range_ptr) { 924 fprintf(stderr, 925 _("failed to build new range with level %s\n"), 926 level_s); 927 goto err_free; 928 } 929 if (context_range_set(context, range_ptr)) { 930 fprintf(stderr, _("failed to set new range %s\n"), 931 range_ptr); 932 goto err_free; 933 } 934 } 935 936 /* Construct the final new context */ 937 if (!(new_con = context_str(context))) { 938 fprintf(stderr, _("failed to convert new context to string\n")); 939 goto err_free; 940 } 941 942 if (security_check_context(new_con) < 0) { 943 fprintf(stderr, _("%s is not a valid context\n"), new_con); 944 send_audit_message(0, old_context, new_con, ttyn); 945 goto err_free; 946 } 947 948 *new_context = strdup(new_con); 949 if (!*new_context) { 950 fprintf(stderr, _("Unable to allocate memory for new_context")); 951 goto err_free; 952 } 953 954 free(type_ptr); 955 free(range_ptr); 956 context_free(context); 957 return 0; 958 959 err_free: 960 free(type_ptr); 961 free(range_ptr); 962 /* Don't free new_con, context_free(context) handles this */ 963 context_free(context); 964 return -1; 965 } 966 967 /** 968 * Take care of any signal setup 969 */ 970 static int set_signal_handles() 971 { 972 sigset_t empty; 973 974 /* Empty the signal mask in case someone is blocking a signal */ 975 if (sigemptyset(&empty)) { 976 fprintf(stderr, _("Unable to obtain empty signal set\n")); 977 return -1; 978 } 979 980 (void)sigprocmask(SIG_SETMASK, &empty, NULL); 981 982 /* Terminate on SIGHUP. */ 983 if (signal(SIGHUP, SIG_DFL) == SIG_ERR) { 984 fprintf(stderr, _("Unable to set SIGHUP handler\n")); 985 return -1; 986 } 987 988 return 0; 989 } 990 991 /************************************************************************ 992 * 993 * All code used for both PAM and shadow passwd goes in this section. 994 * 995 ************************************************************************/ 996 997 int main(int argc, char *argv[]) 998 { 999 security_context_t new_context = NULL; /* target security context */ 1000 security_context_t old_context = NULL; /* original securiy context */ 1001 security_context_t tty_context = NULL; /* current context of tty */ 1002 security_context_t new_tty_context = NULL; /* new context of tty */ 1003 1004 struct passwd pw; /* struct derived from passwd file line */ 1005 char *ttyn = NULL; /* tty path */ 1006 1007 char **old_environ; 1008 int preserve_environment; 1009 1010 int fd; 1011 pid_t childPid = 0; 1012 char *shell_argv0 = NULL; 1013 1014 #ifdef USE_PAM 1015 int rc; 1016 int pam_status; /* pam return code */ 1017 pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */ 1018 1019 /* This is a jump table of functions for PAM to use when it wants to * 1020 * communicate with the user. We'll be using misc_conv(), which is * 1021 * provided for us via pam_misc.h. */ 1022 struct pam_conv pam_conversation = { 1023 misc_conv, 1024 NULL 1025 }; 1026 #endif 1027 1028 /* 1029 * Step 0: Setup 1030 * 1031 * Do some intial setup, including dropping capabilities, checking 1032 * if it makes sense to continue to run newrole, and setting up 1033 * a scrubbed environment. 1034 */ 1035 if (drop_capabilities(FALSE)) { 1036 perror(_("Sorry, newrole failed to drop capabilities\n")); 1037 return -1; 1038 } 1039 if (set_signal_handles()) 1040 return -1; 1041 1042 #ifdef USE_NLS 1043 setlocale(LC_ALL, ""); 1044 bindtextdomain(PACKAGE, LOCALEDIR); 1045 textdomain(PACKAGE); 1046 #endif 1047 1048 old_environ = environ; 1049 environ = NULL; 1050 1051 if (!is_selinux_enabled()) { 1052 fprintf(stderr, _("Sorry, newrole may be used only on " 1053 "a SELinux kernel.\n")); 1054 return -1; 1055 } 1056 1057 if (security_getenforce() < 0) { 1058 fprintf(stderr, _("Could not determine enforcing mode.\n")); 1059 return -1; 1060 } 1061 1062 /* 1063 * Step 1: Parse command line and valid arguments 1064 * 1065 * old_context and ttyn are required for audit logging, 1066 * context validation and pam 1067 */ 1068 if (getprevcon(&old_context)) { 1069 fprintf(stderr, _("failed to get old_context.\n")); 1070 return -1; 1071 } 1072 1073 ttyn = ttyname(STDIN_FILENO); 1074 if (!ttyn || *ttyn == '\0') { 1075 fprintf(stderr, 1076 _("Warning! Could not retrieve tty information.\n")); 1077 } 1078 1079 if (parse_command_line_arguments(argc, argv, ttyn, old_context, 1080 &new_context, &preserve_environment)) 1081 return -1; 1082 1083 /* 1084 * Step 2: Authenticate the user. 1085 * 1086 * Re-authenticate the user running this program. 1087 * This is just to help confirm user intent (vs. invocation by 1088 * malicious software), not to authorize the operation (which is covered 1089 * by policy). Trusted path mechanism would be preferred. 1090 */ 1091 if (extract_pw_data(&pw)) 1092 goto err_free; 1093 1094 #ifdef USE_PAM 1095 if (read_pam_config()) { 1096 fprintf(stderr, 1097 _("error on reading PAM service configuration.\n")); 1098 goto err_free; 1099 } 1100 1101 if (app_service_names != NULL && optind < argc) { 1102 if (strcmp(argv[optind], "-c") == 0 && optind < (argc - 1)) { 1103 /* 1104 * Check for a separate pam service name for the 1105 * command when invoked by newrole. 1106 */ 1107 char *cmd = NULL; 1108 rc = sscanf(argv[optind + 1], "%as", &cmd); 1109 if (rc != EOF && cmd) { 1110 char *app_service_name = 1111 (char *)hashtab_search(app_service_names, 1112 cmd); 1113 free(cmd); 1114 if (app_service_name != NULL) 1115 service_name = app_service_name; 1116 } 1117 } 1118 } 1119 1120 pam_status = pam_start(service_name, pw.pw_name, &pam_conversation, 1121 &pam_handle); 1122 if (pam_status != PAM_SUCCESS) { 1123 fprintf(stderr, _("failed to initialize PAM\n")); 1124 goto err_free; 1125 } 1126 1127 if (!authenticate_via_pam(ttyn, pam_handle)) 1128 #else 1129 if (!authenticate_via_shadow_passwd(pw.pw_name)) 1130 #endif 1131 { 1132 fprintf(stderr, _("newrole: incorrect password for %s\n"), 1133 pw.pw_name); 1134 send_audit_message(0, old_context, new_context, ttyn); 1135 goto err_close_pam; 1136 } 1137 1138 /* 1139 * Step 3: Handle relabeling of the tty. 1140 * 1141 * Once we authenticate the user, we know that we want to proceed with 1142 * the action. Prior to this point, no changes are made the to system. 1143 */ 1144 fd = relabel_tty(ttyn, new_context, &tty_context, &new_tty_context); 1145 if (fd < 0) 1146 goto err_close_pam; 1147 1148 /* 1149 * Step 4: Fork 1150 * 1151 * Fork, allowing parent to clean up after shell has executed. 1152 * Child: reopen stdin, stdout, stderr and exec shell 1153 * Parnet: wait for child to die and restore tty's context 1154 */ 1155 childPid = fork(); 1156 if (childPid < 0) { 1157 /* fork failed, no child to worry about */ 1158 int errsv = errno; 1159 fprintf(stderr, _("newrole: failure forking: %s"), 1160 strerror(errsv)); 1161 if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) 1162 fprintf(stderr, _("Unable to restore tty label...\n")); 1163 if (close(fd)) 1164 fprintf(stderr, _("Failed to close tty properly\n")); 1165 goto err_close_pam; 1166 } else if (childPid) { 1167 /* PARENT 1168 * It doesn't make senes to exit early on errors at this point, 1169 * since we are doing cleanup which needs to be done. 1170 * We can exit with a bad rc though 1171 */ 1172 pid_t pid; 1173 int exit_code = 0; 1174 int status; 1175 1176 do { 1177 pid = wait(&status); 1178 } while (pid < 0 && errno == EINTR); 1179 1180 /* Preserve child exit status, unless there is another error. */ 1181 if (WIFEXITED(status)) 1182 exit_code = WEXITSTATUS(status); 1183 1184 if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) { 1185 fprintf(stderr, _("Unable to restore tty label...\n")); 1186 exit_code = -1; 1187 } 1188 freecon(tty_context); 1189 freecon(new_tty_context); 1190 if (close(fd)) { 1191 fprintf(stderr, _("Failed to close tty properly\n")); 1192 exit_code = -1; 1193 } 1194 #ifdef USE_PAM 1195 #ifdef NAMESPACE_PRIV 1196 pam_status = pam_close_session(pam_handle, 0); 1197 if (pam_status != PAM_SUCCESS) { 1198 fprintf(stderr, "pam_close_session failed with %s\n", 1199 pam_strerror(pam_handle, pam_status)); 1200 exit_code = -1; 1201 } 1202 #endif 1203 rc = pam_end(pam_handle, pam_status); 1204 if (rc != PAM_SUCCESS) { 1205 fprintf(stderr, "pam_end failed with %s\n", 1206 pam_strerror(pam_handle, rc)); 1207 exit_code = -1; 1208 } 1209 hashtab_map(app_service_names, free_hashtab_entry, NULL); 1210 hashtab_destroy(app_service_names); 1211 #endif 1212 free(pw.pw_name); 1213 free(pw.pw_dir); 1214 free(pw.pw_shell); 1215 free(shell_argv0); 1216 return exit_code; 1217 } 1218 1219 /* CHILD */ 1220 /* Close the tty and reopen descriptors 0 through 2 */ 1221 if (ttyn) { 1222 if (close(fd) || close(0) || close(1) || close(2)) { 1223 fprintf(stderr, _("Could not close descriptors.\n")); 1224 goto err_close_pam; 1225 } 1226 fd = open(ttyn, O_RDONLY | O_NONBLOCK); 1227 if (fd != 0) 1228 goto err_close_pam; 1229 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); 1230 fd = open(ttyn, O_RDWR | O_NONBLOCK); 1231 if (fd != 1) 1232 goto err_close_pam; 1233 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); 1234 fd = open(ttyn, O_RDWR | O_NONBLOCK); 1235 if (fd != 2) 1236 goto err_close_pam; 1237 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); 1238 1239 } 1240 /* 1241 * Step 5: Execute a new shell with the new context in `new_context'. 1242 * 1243 * Establish context, namesapce and any options for the new shell 1244 */ 1245 if (optind < 1) 1246 optind = 1; 1247 1248 /* This is ugly, but use newrole's argv for the exec'd shells argv */ 1249 if (asprintf(&shell_argv0, "-%s", pw.pw_shell) < 0) { 1250 fprintf(stderr, _("Error allocating shell's argv0.\n")); 1251 shell_argv0 = NULL; 1252 goto err_close_pam; 1253 } 1254 argv[optind - 1] = shell_argv0; 1255 1256 if (setexeccon(new_context)) { 1257 fprintf(stderr, _("Could not set exec context to %s.\n"), 1258 new_context); 1259 goto err_close_pam; 1260 } 1261 #ifdef NAMESPACE_PRIV 1262 /* Ask PAM to setup session for user running this program */ 1263 pam_status = pam_open_session(pam_handle, 0); 1264 if (pam_status != PAM_SUCCESS) { 1265 fprintf(stderr, "pam_open_session failed with %s\n", 1266 pam_strerror(pam_handle, pam_status)); 1267 goto err_close_pam; 1268 } 1269 #endif 1270 1271 if (send_audit_message(1, old_context, new_context, ttyn)) 1272 goto err_close_pam_session; 1273 freecon(old_context); old_context=NULL; 1274 freecon(new_context); new_context=NULL; 1275 1276 #ifdef NAMESPACE_PRIV 1277 if (transition_to_caller_uid()) 1278 goto err_close_pam_session; 1279 #endif 1280 1281 if (drop_capabilities(TRUE)) 1282 goto err_close_pam_session; 1283 1284 /* Handle environment changes */ 1285 if (restore_environment(preserve_environment, old_environ, &pw)) { 1286 fprintf(stderr, _("Unable to restore the environment, " 1287 "aborting\n")); 1288 goto err_close_pam_session; 1289 } 1290 execv(pw.pw_shell, argv + optind - 1); 1291 1292 /* 1293 * Error path cleanup 1294 * 1295 * If we reach here, then we failed to exec the new shell. 1296 */ 1297 perror(_("failed to exec shell\n")); 1298 err_close_pam_session: 1299 #ifdef NAMESPACE_PRIV 1300 pam_status = pam_close_session(pam_handle, 0); 1301 if (pam_status != PAM_SUCCESS) 1302 fprintf(stderr, "pam_close_session failed with %s\n", 1303 pam_strerror(pam_handle, pam_status)); 1304 #endif 1305 err_close_pam: 1306 #ifdef USE_PAM 1307 rc = pam_end(pam_handle, pam_status); 1308 if (rc != PAM_SUCCESS) 1309 fprintf(stderr, "pam_end failed with %s\n", 1310 pam_strerror(pam_handle, rc)); 1311 #endif 1312 err_free: 1313 freecon(tty_context); 1314 freecon(new_tty_context); 1315 freecon(old_context); 1316 freecon(new_context); 1317 free(pw.pw_name); 1318 free(pw.pw_dir); 1319 free(pw.pw_shell); 1320 free(shell_argv0); 1321 #ifdef USE_PAM 1322 if (app_service_names) { 1323 hashtab_map(app_service_names, free_hashtab_entry, NULL); 1324 hashtab_destroy(app_service_names); 1325 } 1326 #endif 1327 return -1; 1328 } /* main() */

policycoreutils-2.1.13/restorecond/restorecond.c

Location Tool Test ID Issue
restorecond.c:106:2 gcc unused-result write_pid_file ignoring return value of 'write', declared with attribute warn_unused_result
restorecond.c:211:12 clang-analyzer Access to field 'pw_dir' results in a dereference of a null pointer (loaded from variable 'pwd')
restorecond.c:224:9 gcc unused-result main ignoring return value of 'daemon', declared with attribute warn_unused_result
  1 /*
  2  * restorecond
  3  *
  4  * Copyright (C) 2006-2009 Red Hat 
  5  * see file 'COPYING' for use and warranty information
  6  *
  7  * This program is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License as
  9  * published by the Free Software Foundation; either version 2 of
 10  * the License, or (at your option) any later version.
 11  * 
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16 .* 
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     
 20  * 02111-1307  USA
 21  *
 22  * Authors:  
 23  *   Dan Walsh <dwalsh@redhat.com>
 24  *
 25 */
 26 
 27 /* 
 28  * PURPOSE:
 29  * This daemon program watches for the creation of files listed in a config file
 30  * and makes sure that there security context matches the systems defaults
 31  *
 32  * USAGE:
 33  * restorecond [-d] [-u] [-v] [-f restorecond_file ]
 34  * 
 35  * -d   Run in debug mode
 36  * -f   Use alternative restorecond_file
 37  * -u   Run in user mode
 38  * -v   Run in verbose mode (Report missing files)
 39  *
 40  * EXAMPLE USAGE:
 41  * restorecond
 42  *
 43  */
 44 
 45 #define _GNU_SOURCE
 46 #include <sys/inotify.h>
 47 #include <errno.h>
 48 #include <stdio.h>
 49 #include <stdlib.h>
 50 #include <signal.h>
 51 #include <string.h>
 52 #include <unistd.h>
 53 #include "../setfiles/restore.h"
 54 #include <sys/types.h>
 55 #include <syslog.h>
 56 #include <limits.h>
 57 #include <pwd.h>
 58 #include <sys/stat.h>
 59 #include <string.h>
 60 #include <stdio.h>
 61 #include <fcntl.h>
 62 #include "restorecond.h"
 63 #include "utmpwatcher.h"
 64 
 65 const char *homedir;
 66 static int master_fd = -1;
 67 
 68 static char *server_watch_file  = "/etc/selinux/restorecond.conf";
 69 static char *user_watch_file  = "/etc/selinux/restorecond_user.conf";
 70 static char *watch_file;
 71 static struct restore_opts r_opts;
 72 
 73 #include <selinux/selinux.h>
 74 
 75 int debug_mode = 0;
 76 int terminate = 0;
 77 int master_wd = -1;
 78 int run_as_user = 0;
 79 
 80 static void done(void) {
 81 	watch_list_free(master_fd);
 82 	close(master_fd);
 83 	utmpwatcher_free();
 84 	matchpathcon_fini();
 85 }
 86 
 87 static const char *pidfile = "/var/run/restorecond.pid";
 88 
 89 static int write_pid_file(void)
 90 {
 91 	int pidfd, len;
 92 	char val[16];
 93 
 94 	len = snprintf(val, sizeof(val), "%u\n", getpid());
 95 	if (len < 0) {
 96 		syslog(LOG_ERR, "Pid error (%s)", strerror(errno));
 97 		pidfile = 0;
 98 		return 1;
 99 	}
100 	pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
101 	if (pidfd < 0) {
102 		syslog(LOG_ERR, "Unable to set pidfile (%s)", strerror(errno));
103 		pidfile = 0;
104 		return 1;
105 	}
106 	(void)write(pidfd, val, (unsigned int)len);
ignoring return value of 'write', declared with attribute warn_unused_result
(emitted by gcc)
107 close(pidfd); 108 return 0; 109 } 110 111 /* 112 * SIGTERM handler 113 */ 114 static void term_handler() 115 { 116 terminate = 1; 117 /* trigger a failure in the watch */ 118 close(master_fd); 119 } 120 121 static void usage(char *program) 122 { 123 printf("%s [-d] [-f restorecond_file ] [-u] [-v] \n", program); 124 } 125 126 void exitApp(const char *msg) 127 { 128 perror(msg); 129 exit(-1); 130 } 131 132 /* 133 Add a file to the watch list. We are watching for file creation, so we actually 134 put the watch on the directory and then examine all files created in that directory 135 to see if it is one that we are watching. 136 */ 137 138 int main(int argc, char **argv) 139 { 140 int opt; 141 struct sigaction sa; 142 143 memset(&r_opts, 0, sizeof(r_opts)); 144 145 r_opts.progress = 0; 146 r_opts.count = 0; 147 r_opts.debug = 0; 148 r_opts.change = 1; 149 r_opts.verbose = 0; 150 r_opts.logging = 0; 151 r_opts.rootpath = NULL; 152 r_opts.rootpathlen = 0; 153 r_opts.outfile = NULL; 154 r_opts.force = 0; 155 r_opts.hard_links = 0; 156 r_opts.abort_on_error = 0; 157 r_opts.add_assoc = 0; 158 r_opts.expand_realpath = 0; 159 r_opts.fts_flags = FTS_PHYSICAL; 160 r_opts.selabel_opt_validate = NULL; 161 r_opts.selabel_opt_path = NULL; 162 r_opts.ignore_enoent = 1; 163 164 restore_init(&r_opts); 165 /* If we are not running SELinux then just exit */ 166 if (is_selinux_enabled() != 1) return 0; 167 168 /* Register sighandlers */ 169 sa.sa_flags = 0; 170 sa.sa_handler = term_handler; 171 sigemptyset(&sa.sa_mask); 172 sigaction(SIGTERM, &sa, NULL); 173 174 set_matchpathcon_flags(MATCHPATHCON_NOTRANS); 175 176 exclude_non_seclabel_mounts(); 177 atexit( done ); 178 while ((opt = getopt(argc, argv, "hdf:uv")) > 0) { 179 switch (opt) { 180 case 'd': 181 debug_mode = 1; 182 break; 183 case 'f': 184 watch_file = optarg; 185 break; 186 case 'u': 187 run_as_user = 1; 188 break; 189 case 'h': 190 usage(argv[0]); 191 exit(0); 192 break; 193 case 'v': 194 r_opts.verbose++; 195 break; 196 case '?': 197 usage(argv[0]); 198 exit(-1); 199 } 200 } 201 202 master_fd = inotify_init(); 203 if (master_fd < 0) 204 exitApp("inotify_init"); 205 206 uid_t uid = getuid(); 207 struct passwd *pwd = getpwuid(uid); 208 if (!pwd) 209 exitApp("getpwuid"); 210 211 homedir = pwd->pw_dir;
Access to field 'pw_dir' results in a dereference of a null pointer (loaded from variable 'pwd')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

212 if (uid != 0) { 213 if (run_as_user) 214 return server(master_fd, user_watch_file); 215 if (start() != 0) 216 return server(master_fd, user_watch_file); 217 return 0; 218 } 219 220 watch_file = server_watch_file; 221 read_config(master_fd, watch_file); 222 223 if (!debug_mode) 224 daemon(0, 0);
ignoring return value of 'daemon', declared with attribute warn_unused_result
(emitted by gcc)
225 226 write_pid_file(); 227 228 while (watch(master_fd, watch_file) == 0) { 229 }; 230 231 watch_list_free(master_fd); 232 close(master_fd); 233 matchpathcon_fini(); 234 if (pidfile) 235 unlink(pidfile); 236 237 return 0; 238 }

policycoreutils-2.1.13/restorecond/stringslist.c

Location Tool Test ID Issue
stringslist.c:50:2 clang-analyzer Access to field 'string' results in a dereference of a null pointer (loaded from variable 'newptr')
  1 /*
  2  * Copyright (C) 2006, 2008 Red Hat 
  3  * see file 'COPYING' for use and warranty information
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation; either version 2 of
  8  * the License, or (at your option) any later version.
  9  * 
 10  * This program is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  * GNU General Public License for more details.
 14 .* 
 15  * You should have received a copy of the GNU General Public License
 16  * along with this program; if not, write to the Free Software
 17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     
 18  * 02111-1307  USA
 19  *
 20  * Authors:  
 21  *   Dan Walsh <dwalsh@redhat.com>
 22  *
 23 */
 24 
 25 #include <string.h>
 26 #include <stdio.h>
 27 #include <stdlib.h>
 28 #include "stringslist.h"
 29 #include "restorecond.h"
 30 #include <fnmatch.h>
 31 
 32 /* Sorted lists */
 33 void strings_list_add(struct stringsList **list, const char *string)
 34 {
 35 	struct stringsList *ptr = *list;
 36 	struct stringsList *prev = NULL;
 37 	struct stringsList *newptr = NULL;
 38 	while (ptr) {
 39 		int cmp = strcmp(string, ptr->string);
 40 		if (cmp < 0)
 41 			break;	/* Not on list break out to add */
 42 		if (cmp == 0)
 43 			return;	/* Already on list */
 44 		prev = ptr;
 45 		ptr = ptr->next;
 46 	}
 47 	newptr = calloc(1, sizeof(struct stringsList));
 48 	if (!newptr)
 49 		exitApp("Out of Memory");
 50 	newptr->string = strdup(string);
Access to field 'string' results in a dereference of a null pointer (loaded from variable 'newptr')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

51 newptr->next = ptr; 52 if (prev) 53 prev->next = newptr; 54 else 55 *list = newptr; 56 } 57 58 int strings_list_find(struct stringsList *ptr, const char *string, int *exact) 59 { 60 while (ptr) { 61 *exact = strcmp(ptr->string, string) == 0; 62 int cmp = fnmatch(ptr->string, string, 0); 63 if (cmp == 0) 64 return 0; /* Match found */ 65 ptr = ptr->next; 66 } 67 return -1; 68 } 69 70 void strings_list_free(struct stringsList *ptr) 71 { 72 struct stringsList *prev = NULL; 73 while (ptr) { 74 free(ptr->string); 75 prev = ptr; 76 ptr = ptr->next; 77 free(prev); 78 } 79 } 80 81 int strings_list_diff(struct stringsList *from, struct stringsList *to) 82 { 83 while (from != NULL && to != NULL) { 84 if (strcmp(from->string, to->string) != 0) 85 return 1; 86 from = from->next; 87 to = to->next; 88 } 89 if (from != NULL || to != NULL) 90 return 1; 91 return 0; 92 } 93 94 void strings_list_print(struct stringsList *ptr) 95 { 96 while (ptr) { 97 printf("%s\n", ptr->string); 98 ptr = ptr->next; 99 } 100 } 101 102 #ifdef TEST 103 void exitApp(const char *msg) 104 { 105 perror(msg); 106 exit(-1); 107 } 108 109 int main(int argc, char **argv) 110 { 111 struct stringsList *list = NULL; 112 struct stringsList *list1 = NULL; 113 strings_list_add(&list, "/etc/resolv.conf"); 114 strings_list_add(&list, "/etc/walsh"); 115 strings_list_add(&list, "/etc/mtab"); 116 strings_list_add(&list, "/etc/walsh"); 117 if (strings_list_diff(list, list) != 0) 118 printf("strings_list_diff test1 bug\n"); 119 strings_list_add(&list1, "/etc/walsh"); 120 if (strings_list_diff(list, list1) == 0) 121 printf("strings_list_diff test2 bug\n"); 122 strings_list_add(&list1, "/etc/walsh"); 123 strings_list_add(&list1, "/etc/walsh/*"); 124 strings_list_add(&list1, "/etc/resolv.conf"); 125 strings_list_add(&list1, "/etc/mtab1"); 126 if (strings_list_diff(list, list1) == 0) 127 printf("strings_list_diff test3 bug\n"); 128 printf("strings list\n"); 129 strings_list_print(list); 130 printf("strings list1\n"); 131 strings_list_find(list1, "/etc/walsh/dan"); 132 strings_list_print(list1); 133 strings_list_free(list); 134 strings_list_free(list1); 135 } 136 #endif

policycoreutils-2.1.13/restorecond/user.c

No issues found

  1 /*
  2  * restorecond
  3  *
  4  * Copyright (C) 2006-2009 Red Hat
  5  * see file 'COPYING' for use and warranty information
  6  *
  7  * This program is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License as
  9  * published by the Free Software Foundation; either version 2 of
 10  * the License, or (at your option) any later version.
 11  *
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16 .*
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 20  * 02111-1307  USA
 21  *
 22  * Authors:
 23  *   Dan Walsh <dwalsh@redhat.com>
 24  *
 25 */
 26 
 27 #define _GNU_SOURCE
 28 #include <sys/inotify.h>
 29 #include <errno.h>
 30 #include <stdio.h>
 31 #include <stdlib.h>
 32 #include <signal.h>
 33 #include <string.h>
 34 #include <unistd.h>
 35 #include <ctype.h>
 36 #include <sys/types.h>
 37 #include <sys/stat.h>
 38 #include <syslog.h>
 39 #include <limits.h>
 40 #include <fcntl.h>
 41 
 42 #include "restorecond.h"
 43 #include "stringslist.h"
 44 #include <glib.h>
 45 #ifdef HAVE_DBUS
 46 #include <dbus/dbus.h>
 47 #include <dbus/dbus-glib.h>
 48 #include <dbus/dbus-glib-lowlevel.h>
 49 
 50 static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
 51 
 52 static const char *PATH="/org/selinux/Restorecond";
 53 //static const char *BUSNAME="org.selinux.Restorecond";
 54 static const char *INTERFACE="org.selinux.RestorecondIface";
 55 static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
 56 
 57 
 58 static DBusHandlerResult
 59 signal_filter (DBusConnection *connection  __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
 60 {
 61   /* User data is the event loop we are running in */
 62   GMainLoop *loop = user_data;
 63 
 64   /* A signal from the bus saying we are about to be disconnected */
 65   if (dbus_message_is_signal
 66         (message, INTERFACE, "Stop")) {
 67 
 68       /* Tell the main loop to quit */
 69       g_main_loop_quit (loop);
 70       /* We have handled this message, don't pass it on */
 71       return DBUS_HANDLER_RESULT_HANDLED;
 72   }
 73   /* A Ping signal on the com.burtonini.dbus.Signal interface */
 74   else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
 75     DBusError error;
 76     dbus_error_init (&error);
 77     g_print("Start received\n");
 78     return DBUS_HANDLER_RESULT_HANDLED;
 79   }
 80   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 81 }
 82 
 83 static int dbus_server(GMainLoop *loop) {
 84     DBusConnection *bus;
 85     DBusError error;
 86     dbus_error_init (&error);
 87     bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
 88     if (bus) {
 89 	dbus_connection_setup_with_g_main (bus, NULL);
 90 
 91 	/* listening to messages from all objects as no path is specified */
 92 	dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
 93 	dbus_connection_add_filter (bus, signal_filter, loop, NULL);
 94 	return 0;
 95     }
 96     return -1;
 97 }
 98 
 99 #endif
100 #include <selinux/selinux.h>
101 #include <sys/file.h>
102 
103 /* size of the event structure, not counting name */
104 #define EVENT_SIZE  (sizeof (struct inotify_event))
105 /* reasonable guess as to size of 1024 events */
106 #define BUF_LEN        (1024 * (EVENT_SIZE + 16))
107 
108 static gboolean
109 io_channel_callback
110  (GIOChannel *source,
111   GIOCondition condition,
112   gpointer data __attribute__((__unused__)))
113 {
114 
115   char buffer[BUF_LEN+1];
116   gsize bytes_read;
117   unsigned int i = 0;
118 
119   if (condition & G_IO_IN) {
120     /* Data is available. */
121     g_io_channel_read_chars
122       (source, buffer,
123        sizeof (buffer),
124        &bytes_read, NULL);
125 
126     if (! bytes_read) {
127 	    /* Sesssion/Terminal Ended */
128 	    exit(0);
129     }
130 
131     while (i < bytes_read) {
132 	    struct inotify_event *event;
133 	    event = (struct inotify_event *)&buffer[i];
134 	    if (debug_mode)
135 		    printf("wd=%d mask=%u cookie=%u len=%u\n",
136 			   event->wd, event->mask,
137 			   event->cookie, event->len);
138 	    if (event->len)
139 		    watch_list_find(event->wd, event->name);
140 
141 	    i += EVENT_SIZE + event->len;
142     }
143   }
144 
145   /* An error happened while reading
146      the file. */
147 
148   if (condition & G_IO_NVAL)
149     return FALSE;
150 
151   /* We have reached the end of the
152      file. */
153 
154   if (condition & G_IO_HUP) {
155     g_io_channel_shutdown (source, 0, NULL);
156     exit(0);
157     return FALSE;
158   }
159 
160   /* Returning TRUE will make sure
161      the callback remains associated
162      to the channel. */
163 
164   return TRUE;
165 }
166 
167 int start() {
168 #ifdef HAVE_DBUS
169 	DBusConnection *bus;
170 	DBusError error;
171 	DBusMessage *message;
172 
173 	/* Get a connection to the session bus */
174 	dbus_error_init (&error);
175 	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
176 	if (!bus) {
177 		if (debug_mode)
178 			g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
179 		dbus_error_free (&error);
180 		return 1;
181 	}
182 
183 
184 	/* Create a new signal "Start" on the interface,
185 	 * from the object  */
186 	message = dbus_message_new_signal (PATH,
187 					   INTERFACE, "Start");
188 	/* Send the signal */
189 	dbus_connection_send (bus, message, NULL);
190 	/* Free the signal now we have finished with it */
191 	dbus_message_unref (message);
192 #endif /* HAVE_DBUS */
193 	return 0;
194 }
195 
196 static int local_server() {
197 	// ! dbus, run as local service
198 	char *ptr=NULL;
199 	if (asprintf(&ptr, "%s/.restorecond", homedir) < 0) {
200 		if (debug_mode)
201 			perror("asprintf");
202 		return -1;
203 	}
204 	int fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
205 	if (debug_mode)
206 		g_warning ("Lock file: %s", ptr);
207 
208 	free(ptr);
209 	if (fd < 0) {
210 		if (debug_mode)
211 			perror("open");
212 		return -1;
213 	}
214 	if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
215 		if (debug_mode)
216 			perror("flock");
217 		return -1;
218 	}
219 	/* watch for stdin/terminal going away */
220 	GIOChannel *in = g_io_channel_unix_new(0);
221 	g_io_add_watch_full( in,
222 			     G_PRIORITY_HIGH,
223 			     G_IO_IN|G_IO_ERR|G_IO_HUP,
224 			     io_channel_callback, NULL, NULL);
225 
226 	return 0;
227 }
228 
229 int server(int master_fd, const char *watch_file) {
230     GMainLoop *loop;
231 
232     loop = g_main_loop_new (NULL, FALSE);
233 
234 #ifdef HAVE_DBUS
235     if (dbus_server(loop) != 0)
236 #endif /* HAVE_DBUS */
237 	    if (local_server())
238 		    goto end;
239 
240     read_config(master_fd, watch_file);
241 
242     if (watch_list_isempty()) goto end;
243 
244     set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
245 
246     GIOChannel *c = g_io_channel_unix_new(master_fd);
247 
248     g_io_add_watch_full( c,
249 			 G_PRIORITY_HIGH,
250 			 G_IO_IN|G_IO_ERR|G_IO_HUP,
251 			 io_channel_callback, NULL, NULL);
252 
253     g_main_loop_run (loop);
254 
255 end:
256     g_main_loop_unref (loop);
257     return 0;
258 }

policycoreutils-2.1.13/restorecond/utmpwatcher.c

No issues found

  1 /*
  2  * utmpwatcher.c
  3  *
  4  * Copyright (C) 2006 Red Hat 
  5  * see file 'COPYING' for use and warranty information
  6  *
  7  * This program is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License as
  9  * published by the Free Software Foundation; either version 2 of
 10  * the License, or (at your option) any later version.
 11  * 
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16 .* 
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     
 20  * 02111-1307  USA
 21  *
 22  * Authors:  
 23  *   Dan Walsh <dwalsh@redhat.com>
 24  *
 25  *
 26 */
 27 
 28 #define _GNU_SOURCE
 29 #include <sys/inotify.h>
 30 #include <stdio.h>
 31 #include <stdlib.h>
 32 #include <string.h>
 33 #include <sys/types.h>
 34 #include <sys/stat.h>
 35 #include <syslog.h>
 36 
 37 #include <limits.h>
 38 #include <utmp.h>
 39 #include <sys/types.h>
 40 #include <pwd.h>
 41 #include "restorecond.h"
 42 #include "utmpwatcher.h"
 43 #include "stringslist.h"
 44 
 45 static struct stringsList *utmp_ptr = NULL;
 46 static int utmp_wd = -1;
 47 
 48 unsigned int utmpwatcher_handle(int inotify_fd, int wd)
 49 {
 50 	int changed = 0;
 51 	struct utmp u;
 52 	char *utmp_path = "/var/run/utmp";
 53 	struct stringsList *prev_utmp_ptr = utmp_ptr;
 54 	if (wd != utmp_wd)
 55 		return -1;
 56 
 57 	utmp_ptr = NULL;
 58 	FILE *cfg = fopen(utmp_path, "r");
 59 	if (!cfg)
 60 		exitApp("Error reading utmp file.");
 61 
 62 	while (fread(&u, sizeof(struct utmp), 1, cfg) > 0) {
 63 		if (u.ut_type == USER_PROCESS)
 64 			strings_list_add(&utmp_ptr, u.ut_user);
 65 	}
 66 	fclose(cfg);
 67 	if (utmp_wd >= 0)
 68 		inotify_rm_watch(inotify_fd, utmp_wd);
 69 
 70 	utmp_wd =
 71 	    inotify_add_watch(inotify_fd, utmp_path, IN_MOVED_FROM | IN_MODIFY);
 72 	if (utmp_wd == -1)
 73 		exitApp("Error watching utmp file.");
 74 
 75 	changed = strings_list_diff(prev_utmp_ptr, utmp_ptr);
 76 	if (prev_utmp_ptr) {
 77 		strings_list_free(prev_utmp_ptr);
 78 	}
 79 	return changed;
 80 }
 81 
 82 static void watch_file(int inotify_fd, const char *file)
 83 {
 84 	struct stringsList *ptr = utmp_ptr;
 85 
 86 	while (ptr) {
 87 		struct passwd *pwd = getpwnam(ptr->string);
 88 		if (pwd) {
 89 			char *path = NULL;
 90 			if (asprintf(&path, "%s%s", pwd->pw_dir, file) < 0)
 91 				exitApp("Error allocating memory.");
 92 			watch_list_add(inotify_fd, path);
 93 			free(path);
 94 		}
 95 		ptr = ptr->next;
 96 	}
 97 }
 98 
 99 void utmpwatcher_add(int inotify_fd, const char *path)
100 {
101 	if (utmp_ptr == NULL) {
102 		utmpwatcher_handle(inotify_fd, utmp_wd);
103 	}
104 	watch_file(inotify_fd, path);
105 }
106 
107 void utmpwatcher_free(void)
108 {
109 	if (utmp_ptr)
110 		strings_list_free(utmp_ptr);
111 }
112 
113 #ifdef TEST
114 int main(int argc, char **argv)
115 {
116 	read_utmp();
117 	return 0;
118 }
119 #endif

policycoreutils-2.1.13/restorecond/watch.c

Location Tool Test ID Issue
watch.c:82:2 clang-analyzer Access to field 'wd' results in a dereference of a null pointer (loaded from variable 'ptr')
  1 #define _GNU_SOURCE
  2 #include <sys/inotify.h>
  3 #include <errno.h>
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <unistd.h>
  8 #include <ctype.h>
  9 #include <sys/types.h>
 10 #include <syslog.h>
 11 #include "../setfiles/restore.h"
 12 #include <glob.h>
 13 #include <libgen.h>
 14 #include <sys/stat.h>
 15 #include <string.h>
 16 #include <stdio.h>
 17 #include <fcntl.h>
 18 #include <selinux/selinux.h>
 19 #include "restorecond.h"
 20 #include "stringslist.h"
 21 #include "utmpwatcher.h"
 22 
 23 /* size of the event structure, not counting name */
 24 #define EVENT_SIZE  (sizeof (struct inotify_event))
 25 /* reasonable guess as to size of 1024 events */
 26 #define BUF_LEN        (1024 * (EVENT_SIZE + 16))
 27 
 28 
 29 struct watchList {
 30 	struct watchList *next;
 31 	int wd;
 32 	char *dir;
 33 	struct stringsList *files;
 34 };
 35 struct watchList *firstDir = NULL;
 36 
 37 int watch_list_isempty() {
 38 	return firstDir == NULL;
 39 }
 40 
 41 void watch_list_add(int fd, const char *path)
 42 {
 43 	struct watchList *ptr = NULL;
 44 	size_t i = 0;
 45 	struct watchList *prev = NULL;
 46 	glob_t globbuf;
 47 	char *x = strdup(path);
 48 	if (!x) exitApp("Out of Memory");
 49 	char *file = basename(x);
 50 	char *dir = dirname(x);
 51 	ptr = firstDir;
 52 
 53 	if (exclude(path)) goto end;
 54 
 55 	globbuf.gl_offs = 1;
 56 	if (glob(path,
 57 		 GLOB_TILDE | GLOB_PERIOD,
 58 		 NULL,
 59 		 &globbuf) >= 0) {
 60 		for (i=0; i < globbuf.gl_pathc; i++) {
 61 		  int len = strlen(globbuf.gl_pathv[i]) -2;
 62 		  if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) continue;
 63 		  if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) continue;
 64 		  if (process_one_realpath(globbuf.gl_pathv[i], 0) > 0)
 65 			  process_one_realpath(globbuf.gl_pathv[i], 1);
 66 		}
 67 		globfree(&globbuf);
 68 	}
 69 
 70 	while (ptr != NULL) {
 71 		if (strcmp(dir, ptr->dir) == 0) {
 72 			strings_list_add(&ptr->files, file);
 73 			goto end;
 74 		}
 75 		prev = ptr;
 76 		ptr = ptr->next;
 77 	}
 78 	ptr = calloc(1, sizeof(struct watchList));
 79 
 80 	if (!ptr) exitApp("Out of Memory");
 81 
 82 	ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
Access to field 'wd' results in a dereference of a null pointer (loaded from variable 'ptr')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

83 if (ptr->wd == -1) { 84 free(ptr); 85 if (! run_as_user) 86 syslog(LOG_ERR, "Unable to watch (%s) %s\n", 87 path, strerror(errno)); 88 goto end; 89 } 90 91 ptr->dir = strdup(dir); 92 if (!ptr->dir) 93 exitApp("Out of Memory"); 94 95 strings_list_add(&ptr->files, file); 96 if (prev) 97 prev->next = ptr; 98 else 99 firstDir = ptr; 100 101 if (debug_mode) 102 printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file); 103 104 end: 105 free(x); 106 return; 107 } 108 109 /* 110 A file was in a direcroty has been created. This function checks to 111 see if it is one that we are watching. 112 */ 113 114 int watch_list_find(int wd, const char *file) 115 { 116 struct watchList *ptr = NULL; 117 ptr = firstDir; 118 if (debug_mode) 119 printf("%d: File=%s\n", wd, file); 120 while (ptr != NULL) { 121 if (ptr->wd == wd) { 122 int exact=0; 123 if (strings_list_find(ptr->files, file, &exact) == 0) { 124 char *path = NULL; 125 if (asprintf(&path, "%s/%s", ptr->dir, file) < 126 0) 127 exitApp("Error allocating memory."); 128 129 process_one_realpath(path, 0); 130 free(path); 131 return 0; 132 } 133 if (debug_mode) 134 strings_list_print(ptr->files); 135 136 /* Not found in this directory */ 137 return -1; 138 } 139 ptr = ptr->next; 140 } 141 /* Did not find a directory */ 142 return -1; 143 } 144 145 void watch_list_free(int fd) 146 { 147 struct watchList *ptr = NULL; 148 struct watchList *prev = NULL; 149 ptr = firstDir; 150 151 while (ptr != NULL) { 152 inotify_rm_watch(fd, ptr->wd); 153 strings_list_free(ptr->files); 154 free(ptr->dir); 155 prev = ptr; 156 ptr = ptr->next; 157 free(prev); 158 } 159 firstDir = NULL; 160 } 161 162 /* 163 Inotify watch loop 164 */ 165 int watch(int fd, const char *watch_file) 166 { 167 char buf[BUF_LEN]; 168 int len, i = 0; 169 if (firstDir == NULL) return 0; 170 171 len = read(fd, buf, BUF_LEN); 172 if (len < 0) { 173 if (terminate == 0) { 174 syslog(LOG_ERR, "Read error (%s)", strerror(errno)); 175 return 0; 176 } 177 syslog(LOG_ERR, "terminated"); 178 return -1; 179 } else if (!len) 180 /* BUF_LEN too small? */ 181 return -1; 182 while (i < len) { 183 struct inotify_event *event; 184 event = (struct inotify_event *)&buf[i]; 185 if (debug_mode) 186 printf("wd=%d mask=%u cookie=%u len=%u\n", 187 event->wd, event->mask, 188 event->cookie, event->len); 189 if (event->mask & ~IN_IGNORED) { 190 if (event->wd == master_wd) 191 read_config(fd, watch_file); 192 else { 193 switch (utmpwatcher_handle(fd, event->wd)) { 194 case -1: /* Message was not for utmpwatcher */ 195 if (event->len) 196 watch_list_find(event->wd, event->name); 197 break; 198 case 1: /* utmp has changed need to reload */ 199 read_config(fd, watch_file); 200 break; 201 202 default: /* No users logged in or out */ 203 break; 204 } 205 } 206 } 207 208 i += EVENT_SIZE + event->len; 209 } 210 return 0; 211 } 212 213 static void process_config(int fd, FILE * cfg) 214 { 215 char *line_buf = NULL; 216 size_t len = 0; 217 218 while (getline(&line_buf, &len, cfg) > 0) { 219 char *buffer = line_buf; 220 while (isspace(*buffer)) 221 buffer++; 222 if (buffer[0] == '#') 223 continue; 224 int l = strlen(buffer) - 1; 225 if (l <= 0) 226 continue; 227 buffer[l] = 0; 228 if (buffer[0] == '~') { 229 if (run_as_user) { 230 char *ptr=NULL; 231 if (asprintf(&ptr, "%s%s", homedir, &buffer[1]) < 0) 232 exitApp("Error allocating memory."); 233 234 watch_list_add(fd, ptr); 235 free(ptr); 236 } else { 237 utmpwatcher_add(fd, &buffer[1]); 238 } 239 } else { 240 watch_list_add(fd, buffer); 241 } 242 } 243 free(line_buf); 244 } 245 246 /* 247 Read config file ignoring Comment lines 248 Files specified one per line. Files with "~" will be expanded to the logged in users 249 homedirs. 250 */ 251 252 void read_config(int fd, const char *watch_file_path) 253 { 254 255 FILE *cfg = NULL; 256 if (debug_mode) 257 printf("Read Config\n"); 258 259 watch_list_free(fd); 260 261 cfg = fopen(watch_file_path, "r"); 262 if (!cfg){ 263 perror(watch_file_path); 264 exitApp("Error reading config file"); 265 } 266 process_config(fd, cfg); 267 fclose(cfg); 268 269 inotify_rm_watch(fd, master_wd); 270 master_wd = 271 inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY); 272 if (master_wd == -1) 273 exitApp("Error watching config file."); 274 }

policycoreutils-2.1.13/run_init/open_init_pty.c

No issues found

  1 /*                               -*- Mode: C -*- 
  2  * open_init_pty.c --- 
  3  * Author           : Manoj Srivastava ( srivasta@glaurung.internal.golden-gryphon.com ) 
  4  * Created On       : Fri Jan 14 10:48:28 2005
  5  * Created On Node  : glaurung.internal.golden-gryphon.com
  6  * Last Modified By : Manoj Srivastava
  7  * Last Modified On : Thu Sep 15 00:57:00 2005
  8  * Last Machine Used: glaurung.internal.golden-gryphon.com
  9  * Update Count     : 92
 10  * Status           : Unknown, Use with caution!
 11  * HISTORY          : 
 12  * Description      : 
 13  *
 14  * Distributed under the terms of the GNU General Public License v2
 15  *
 16  * open_init_pty
 17  *
 18  * SYNOPSIS:
 19  *
 20  * This program allows a systems administrator to execute daemons
 21  * which need to work in the initrc domain, and which need to have
 22  * pty's as system_u:system_r:initrc_t
 23  *
 24  * USAGE:
 25  *
 26  * * arch-tag: a5583d39-72b9-4cdf-ba1b-5678ea4cbe20
 27  */
 28 
 29 #include <stdio.h>
 30 #include <stdlib.h>
 31 #include <unistd.h>
 32 #include <signal.h>
 33 #include <errno.h>
 34 
 35 #include <sysexits.h>
 36 
 37 #include <pty.h>		/* for openpty and forkpty */
 38 #include <utmp.h>		/* for login_tty */
 39 #include <termios.h>
 40 #include <fcntl.h>
 41 
 42 #include <sys/select.h>
 43 
 44 static struct termios saved_termios;
 45 static int saved_fd = -1;
 46 static enum { RESET, RAW, CBREAK } tty_state = RESET;
 47 
 48 static int tty_semi_raw(int fd)
 49 {
 50 	struct termios buf;
 51 
 52 	if (tty_state == RESET) {
 53 		if (tcgetattr(fd, &saved_termios) < 0) {
 54 			return -1;
 55 		}
 56 	}
 57 
 58 	buf = saved_termios;
 59 	/*
 60 	 * echo off, canonical mode off, extended input processing off,
 61 	 * signal chars off 
 62 	 */
 63 	buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
 64 	/*
 65 	 * no SIGINT on break, CR-to-NL off, input parity check off, do not
 66 	 * strip 8th bit on input,output flow control off
 67 	 */
 68 	buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
 69 	/* Clear size bits, parity checking off */
 70 	buf.c_cflag &= ~(CSIZE | PARENB);
 71 	/* set 8 bits/char */
 72 	buf.c_cflag |= CS8;
 73 	/* Output processing off 
 74 	   buf.c_oflag    &= ~(OPOST); */
 75 
 76 	buf.c_cc[VMIN] = 1;	/* one byte at a time, no timer */
 77 	buf.c_cc[VTIME] = 0;
 78 	if (tcsetattr(fd, TCSANOW, &buf) < 0) {
 79 		return -1;
 80 	}			/* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */
 81 	tty_state = RAW;
 82 	saved_fd = fd;
 83 	return 0;
 84 }
 85 
 86 void tty_atexit(void)
 87 {
 88 	if (tty_state != CBREAK && tty_state != RAW) {
 89 		return;
 90 	}
 91 
 92 	if (tcsetattr(saved_fd, TCSANOW, &saved_termios) < 0) {
 93 		return;
 94 	}			/* end of if(tcsetattr(fileno(stdin), TCSANOW, &buf) < 0) */
 95 	tty_state = RESET;
 96 	return;
 97 }
 98 
 99 int main(int argc, char *argv[])
100 {
101 	pid_t child_pid;
102 	struct termios tty_attr;
103 	struct winsize window_size;
104 	int pty_master;
105 	int retval = 0;
106 
107 	/* for select */
108 	fd_set readfds;
109 	fd_set writefds;
110 	fd_set exceptfds;
111 
112 	int err_count = 0;
113 
114 	/* for sigtimedwait() */
115 	struct timespec timeout;
116 	char buf[16384];
117 
118 	if (argc == 1) {
119 		printf("usage: %s PROGRAM [ARGS]...\n", argv[0]);
120 		exit(1);
121 	}
122 
123 	sigset_t signal_set;
124 	siginfo_t signalinfo;
125 
126 	/* set up SIGCHLD */
127 	sigemptyset(&signal_set);	/* no signals */
128 	sigaddset(&signal_set, SIGCHLD);	/* Add sig child  */
129 	sigprocmask(SIG_BLOCK, &signal_set, NULL);	/* Block the signal */
130 
131 	/* Set both to 0, so sigtimed wait just does a poll */
132 	timeout.tv_sec = 0;
133 	timeout.tv_nsec = 0;
134 
135 	if (isatty(fileno(stdin))) {
136 		/* get terminal parameters associated with stdout */
137 		if (tcgetattr(fileno(stdout), &tty_attr) < 0) {
138 			perror("tcgetattr:");
139 			exit(EX_OSERR);
140 		}
141 
142 		/* end of if(tcsetattr(&tty_attr)) */
143 		/* get window size */
144 		if (ioctl(fileno(stdout), TIOCGWINSZ, &window_size) < 0) {
145 			perror("ioctl stdout:");
146 			exit(1);
147 		}
148 
149 		child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size);
150 	} /* end of if(isatty(fileno(stdin))) */
151 	else {			/* not interactive */
152 		child_pid = forkpty(&pty_master, NULL, NULL, NULL);
153 	}
154 
155 	if (child_pid < 0) {
156 		perror("forkpty():");
157 		fflush(stdout);
158 		fflush(stderr);
159 		exit(EX_OSERR);
160 	}			/* end of if(child_pid < 0) */
161 	if (child_pid == 0) {
162 		/* in the child */
163 		struct termios s_tty_attr;
164 		if (tcgetattr(fileno(stdin), &s_tty_attr)) {
165 			perror("Child:");
166 			fflush(stdout);
167 			fflush(stderr);
168 			exit(EXIT_FAILURE);
169 		}
170 		/* Turn off echo */
171 		s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
172 		/* Also turn of NL to CR?LF on output */
173 		s_tty_attr.c_oflag &= ~(ONLCR);
174 		if (tcsetattr(fileno(stdin), TCSANOW, &s_tty_attr)) {
175 			perror("Child:");
176 			exit(EXIT_FAILURE);
177 		}
178 		{		/* There is no reason to block sigchild for the process we
179 				   shall exec here */
180 			sigset_t chld_signal_set;
181 			/* release SIGCHLD */
182 			sigemptyset(&chld_signal_set);	/* no signals */
183 			sigaddset(&chld_signal_set, SIGCHLD);	/* Add sig child  */
184 			sigprocmask(SIG_UNBLOCK, &chld_signal_set, NULL);	/* Unblock the signal */
185 		}
186 
187 		if (execvp(argv[1], argv + 1)) {
188 			perror("Exec:");
189 			fflush(stdout);
190 			fflush(stderr);
191 			exit(EXIT_FAILURE);
192 		}
193 	}
194 
195 	/* end of if(child_pid == 0) */
196 	/* 
197 	 * OK. Prepare to handle IO from the child. We need to transfer
198 	 * everything from the child's stdout to ours.
199 	 */
200 	FD_ZERO(&readfds);
201 	FD_ZERO(&writefds);
202 	FD_ZERO(&exceptfds);
203 
204 	/*
205 	 * Read current file descriptor flags, preparing to do non blocking reads
206 	 */
207 	retval = fcntl(pty_master, F_GETFL);
208 	if (retval < 0) {
209 		perror("fcntl_get");
210 		fflush(stdout);
211 		fflush(stderr);
212 		exit(EX_IOERR);
213 	}
214 
215 	/* Set the connection to be non-blocking */
216 	if (fcntl(pty_master, F_SETFL, retval | O_NONBLOCK) < 0) {
217 		perror("fcnt_setFlag_nonblock:");
218 		fflush(stdout);
219 		fflush(stderr);
220 		exit(1);
221 	}
222 
223 	FD_SET(pty_master, &readfds);
224 	FD_SET(pty_master, &writefds);
225 	FD_SET(fileno(stdin), &readfds);
226 	if (isatty(fileno(stdin))) {
227 		if (tty_semi_raw(fileno(stdin)) < 0) {
228 			perror("Error: settingraw mode:");
229 			fflush(stdout);
230 			fflush(stderr);
231 		}		/* end of if(tty_raw(fileno(stdin)) < 0) */
232 		if (atexit(tty_atexit) < 0) {
233 			perror("Atexit setup:");
234 			fflush(stdout);
235 			fflush(stderr);
236 		}		/* end of if(atexit(tty_atexit) < 0) */
237 	}
238 
239 	/* ignore return from nice, but lower our priority */
240 	int ignore __attribute__ ((unused)) = nice(19);
241 
242 	/* while no signal, we loop around */
243 	int done = 0;
244 	while (!done) {
245 		struct timeval interval;
246 		fd_set t_readfds;
247 		fd_set t_writefds;
248 		fd_set t_exceptfds;
249 		/*
250 		 * We still use a blocked signal, and check for SIGCHLD every
251 		 * loop, since waiting infinitely did not really help the load
252 		 * when running, say, top. 
253 		 */
254 		interval.tv_sec = 0;
255 		interval.tv_usec = 200000;	/* so, check for signals every 200 milli
256 						   seconds */
257 
258 		t_readfds = readfds;
259 		t_writefds = writefds;
260 		t_exceptfds = exceptfds;
261 
262 		/* check for the signal */
263 		retval = sigtimedwait(&signal_set, &signalinfo, &timeout);
264 
265 		if (retval == SIGCHLD) {
266 			/* child terminated */
267 			done = 1;	/* in case they do not close off their
268 					   file descriptors */
269 		} else {
270 			if (retval < 0) {
271 				if (errno != EAGAIN) {
272 					perror("sigtimedwait");
273 					fflush(stdout);
274 					fflush(stderr);
275 					exit(EX_IOERR);
276 				} else {
277 					/* No signal in set was delivered within the timeout period specified */
278 				}
279 			}
280 		}		/* end of else */
281 
282 		if (select
283 		    (pty_master + 1, &t_readfds, &t_writefds, &t_exceptfds,
284 		     &interval) < 0) {
285 			perror("Select:");
286 			fflush(stdout);
287 			fflush(stderr);
288 			exit(EX_IOERR);
289 		}
290 
291 		if (FD_ISSET(pty_master, &t_readfds)) {
292 			retval = read(pty_master, buf, (unsigned int)16384);
293 			if (retval < 0) {
294 				if (errno != EINTR && errno != EAGAIN) {	/* Nothing left to read?  */
295 					fflush(stdout);
296 					fflush(stderr);
297 					/* fprintf(stderr, "DEBUG: %d: Nothing left to read?\n", __LINE__); */
298 					exit(EXIT_SUCCESS);
299 				}	/* end of else */
300 			} /* end of if(retval < 0) */
301 			else {
302 				if (retval == 0) {
303 					if (++err_count > 5) {	/* child closed connection */
304 						fflush(stdout);
305 						fflush(stderr);
306 						/*fprintf(stderr, "DEBUG: %d: child closed connection?\n", __LINE__); */
307 						exit(EXIT_SUCCESS);
308 					}
309 				} /* end of if(retval == 0) */
310 				else {
311 					ssize_t nleft = retval;
312 					ssize_t nwritten = 0;
313 					char *ptr = buf;
314 					while (nleft > 0) {
315 						if ((nwritten =
316 						     write(fileno(stdout), ptr,
317 							   (unsigned int)nleft))
318 						    <= 0) {
319 							if (errno == EINTR) {
320 								nwritten = 0;
321 							} /* end of if(errno == EINTR) */
322 							else {
323 								perror("write");
324 								fflush(stdout);
325 								fflush(stderr);
326 								exit(EXIT_SUCCESS);
327 							}	/* end of else */
328 						}	/* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */
329 						nleft -= nwritten;
330 						ptr += nwritten;
331 					}	/* end of while(nleft > 0) */
332 
333 					/* fprintf(stderr, "DEBUG: %d: wrote %d\n", __LINE__, retval); */
334 					fflush(stdout);
335 				}	/* end of else */
336 			}	/* end of else */
337 		}
338 		if (FD_ISSET(fileno(stdin), &t_readfds)) {
339 			if (FD_ISSET(pty_master, &t_writefds)) {
340 				retval =
341 				    read(fileno(stdin), buf,
342 					 (unsigned int)16384);
343 				if (retval < 0) {
344 					if (errno != EINTR && errno != EAGAIN) {	/* Nothing left to read?  */
345 						fflush(stdout);
346 						fflush(stderr);
347 						exit(EXIT_SUCCESS);
348 					}	/* end of else */
349 				} /* end of if(retval < 0) */
350 				else {
351 					if (retval == 0) {
352 						if (++err_count > 5) {	/* lost controlling tty */
353 							fflush(stdout);
354 							fflush(stderr);
355 							exit(EXIT_SUCCESS);
356 						}
357 					} /* end of if(retval == 0) */
358 					else {
359 						ssize_t nleft = retval;
360 						ssize_t nwritten = 0;
361 						char *ptr = buf;
362 						while (nleft > 0) {
363 							if ((nwritten =
364 							     write(pty_master,
365 								   ptr,
366 								   (unsigned
367 								    int)nleft))
368 							    <= 0) {
369 								if (errno ==
370 								    EINTR) {
371 									nwritten
372 									    = 0;
373 								} /* end of if(errno == EINTR) */
374 								else {
375 									perror
376 									    ("write");
377 									fflush
378 									    (stdout);
379 									fflush
380 									    (stderr);
381 									exit(EXIT_SUCCESS);
382 								}	/* end of else */
383 							}	/* end of if((nwritten = write(sockfd, ptr, nleft)) <= 0) */
384 							nleft -= nwritten;
385 							ptr += nwritten;
386 						}	/* end of while(nleft > 0) */
387 
388 						fflush(stdout);
389 					}	/* end of else */
390 				}	/* end of else */
391 			}	/* end of if(FD_ISSET(pty_master, &writefds)) */
392 		}		/* something to read on stdin */
393 	}			/* Loop */
394 
395 	fflush(stdout);
396 	fflush(stderr);
397 
398 	exit(EXIT_SUCCESS);
399 }				/* end of main() */

policycoreutils-2.1.13/run_init/run_init.c

No issues found

  1 /************************************************************************
  2  *
  3  * run_init
  4  *
  5  * SYNOPSIS:
  6  *
  7  * This program allows a user to run an /etc/init.d script in the proper context.
  8  *
  9  * USAGE:
 10  *
 11  * run_init <script> <args>
 12  *
 13  * BUILD OPTIONS:
 14  *
 15  * option USE_PAM:
 16  *
 17  * Set the USE_PAM constant if you want to authenticate users via PAM.
 18  * If USE_PAM is not set, users will be authenticated via direct
 19  * access to the shadow password file.
 20  *
 21  * If you decide to use PAM must be told how to handle run_init.  A
 22  * good rule-of-thumb might be to tell PAM to handle run_init in the
 23  * same way it handles su, except that you should remove the pam_rootok.so
 24  * entry so that even root must re-authenticate to run the init scripts
 25  * in the proper context.
 26  *
 27  * If you choose not to use PAM, make sure you have a shadow passwd file
 28  * in /etc/shadow.  You can use a simlink if your shadow passwd file
 29  * lives in another directory.  Example:
 30  *   su
 31  *   cd /etc
 32  *   ln -s /etc/auth/shadow shadow
 33  *
 34  * If you decide not to use PAM, you will also have to make run_init
 35  * setuid root, so that it can read the shadow passwd file.
 36  * 
 37  *
 38  *************************************************************************/
 39 
 40 #include <stdio.h>
 41 #include <stdlib.h>		/* for malloc(), realloc(), free() */
 42 #include <pwd.h>		/* for getpwuid() */
 43 #include <sys/types.h>		/* to make getuid() and getpwuid() happy */
 44 #include <sys/wait.h>		/* for wait() */
 45 #include <sys/stat.h>		/* for struct stat and friends */
 46 #include <getopt.h>		/* for getopt_long() form of getopt() */
 47 #include <selinux/selinux.h>
 48 #include <selinux/get_default_type.h>
 49 #include <selinux/context.h>	/* for context-mangling functions */
 50 #include <fcntl.h>
 51 #include <ctype.h>
 52 #include <limits.h>
 53 #ifdef USE_AUDIT
 54 #include <libaudit.h>
 55 #endif
 56 #ifdef USE_NLS
 57 #include <libintl.h>
 58 #include <locale.h>
 59 #define _(msgid) gettext (msgid)
 60 #else
 61 #define _(msgid) (msgid)
 62 #endif
 63 #ifndef PACKAGE
 64 #define PACKAGE "policycoreutils"	/* the name of this package lang translation */
 65 #endif
 66 /* USAGE_STRING describes the command-line args of this program. */
 67 #define USAGE_STRING _("USAGE: run_init <script> <args ...>\n\
 68   where: <script> is the name of the init script to run,\n\
 69          <args ...> are the arguments to that script.")
 70 
 71 #define CONTEXT_FILE "initrc_context"
 72 #ifdef USE_PAM
 73 
 74 /************************************************************************
 75  *
 76  * All PAM code goes in this section.
 77  *
 78  ************************************************************************/
 79 
 80 #include <unistd.h>		/* for getuid(), exit(), getopt() */
 81 
 82 #include <security/pam_appl.h>	/* for PAM functions */
 83 #include <security/pam_misc.h>	/* for misc_conv PAM utility function */
 84 
 85 #define SERVICE_NAME "run_init"	/* the name of this program for PAM */
 86 				  /* The file containing the context to run 
 87 				   * the scripts under.                     */
 88 
 89 int authenticate_via_pam(const struct passwd *);
 90 
 91 /* authenticate_via_pam()
 92  *
 93  * in:     p_passwd_line - struct containing data from our user's line in 
 94  *                         the passwd file.
 95  * out:    nothing
 96  * return: value   condition
 97  *         -----   ---------
 98  *           1     PAM thinks that the user authenticated themselves properly
 99  *           0     otherwise
100  *
101  * This function uses PAM to authenticate the user running this
102  * program.  This is the only function in this program that makes PAM
103  * calls.
104  *
105  */
106 
107 int authenticate_via_pam(const struct passwd *p_passwd_line)
108 {
109 
110 	int result = 0;		/* our result, set to 0 (not authenticated) by default */
111 	pam_handle_t *pam_handle;	/* opaque handle used by all PAM functions */
112 
113 	/* This is a jump table of functions for PAM to use when it wants to *
114 	 * communicate with the user.  We'll be using misc_conv(), which is  *
115 	 * provided for us via pam_misc.h.                                   */
116 	struct pam_conv pam_conversation = {
117 		misc_conv,
118 		NULL
119 	};
120 
121 	/* Make `p_pam_handle' a valid PAM handle so we can use it when *
122 	 * calling PAM functions.                                       */
123 	if (PAM_SUCCESS != pam_start(SERVICE_NAME,
124 				     p_passwd_line->pw_name,
125 				     &pam_conversation, &pam_handle)) {
126 		fprintf(stderr, _("failed to initialize PAM\n"));
127 		exit(-1);
128 	}
129 
130 	/* Ask PAM to authenticate the user running this program */
131 	if (PAM_SUCCESS == pam_authenticate(pam_handle, 0)) {
132 		result = 1;	/* user authenticated OK! */
133 	}
134 
135 	/* If we were successful, call pam_acct_mgmt() to reset the
136          * pam_tally failcount.
137          */
138 	if (result && (PAM_SUCCESS != pam_acct_mgmt(pam_handle, 0)) ) {
139 		fprintf(stderr, _("failed to get account information\n"));
140 		exit(-1);
141 	}	
142 
143 	/* We're done with PAM.  Free `pam_handle'. */
144 	pam_end(pam_handle, PAM_SUCCESS);
145 
146 	return (result);
147 
148 }				/* authenticate_via_pam() */
149 
150 #else				/* else !USE_PAM */
151 
152 /************************************************************************
153  *
154  * All shadow passwd code goes in this section.
155  *
156  ************************************************************************/
157 
158 #include <unistd.h>		/* for getuid(), exit(), crypt() */
159 #include <shadow.h>		/* for shadow passwd functions */
160 #include <string.h>		/* for strlen(), memset() */
161 
162 #define PASSWORD_PROMPT _("Password:")	/* prompt for getpass() */
163 
164 int authenticate_via_shadow_passwd(const struct passwd *);
165 
166 /* authenticate_via_shadow_passwd()
167  *
168  * in:     p_passwd_line - struct containing data from our user's line in 
169  *                         the passwd file.
170  * out:    nothing
171  * return: value   condition
172  *         -----   ---------
173  *           1     user authenticated themselves properly according to the
174  *                 shadow passwd file.
175  *           0     otherwise
176  *
177  * This function uses the shadow passwd file to authenticate the user running
178  * this program.
179  *
180  */
181 
182 int authenticate_via_shadow_passwd(const struct passwd *p_passwd_line)
183 {
184 
185 	struct spwd *p_shadow_line;	/* struct derived from shadow passwd file line */
186 	char *unencrypted_password_s;	/* unencrypted password input by user */
187 	char *encrypted_password_s;	/* user's password input after being crypt()ed */
188 
189 	/* Make `p_shadow_line' point to the data from the current user's *
190 	 * line in the shadow passwd file.                                */
191 	setspent();		/* Begin access to the shadow passwd file. */
192 	p_shadow_line = getspnam(p_passwd_line->pw_name);
193 	endspent();		/* End access to the shadow passwd file. */
194 	if (!(p_shadow_line)) {
195 		fprintf(stderr,
196 			_
197 			("Cannot find your entry in the shadow passwd file.\n"));
198 		exit(-1);
199 	}
200 
201 	/* Ask user to input unencrypted password */
202 	if (!(unencrypted_password_s = getpass(PASSWORD_PROMPT))) {
203 		fprintf(stderr, _("getpass cannot open /dev/tty\n"));
204 		exit(-1);
205 	}
206 
207 	/* Use crypt() to encrypt user's input password.  Clear the *
208 	 * unencrypted password as soon as we're done, so it is not * 
209 	 * visible to memory snoopers.                              */
210 	encrypted_password_s = crypt(unencrypted_password_s,
211 				     p_shadow_line->sp_pwdp);
212 	memset(unencrypted_password_s, 0, strlen(unencrypted_password_s));
213 
214 	/* Return 1 (authenticated) iff the encrypted version of the user's *
215 	 * input password matches the encrypted password stored in the      *
216 	 * shadow password file.                                            */
217 	return (!strcmp(encrypted_password_s, p_shadow_line->sp_pwdp));
218 
219 }				/* authenticate_via_shadow_passwd() */
220 
221 #endif				/* if/else USE_PAM */
222 
223 /*
224  * authenticate_user()
225  *
226  * Authenticate the user.
227  *
228  * in:		nothing
229  * out:		nothing
230  * return:	0 When success
231  *		-1 When failure
232  */
233 int authenticate_user()
234 {
235 
236 #define INITLEN 255
237 	struct passwd *p_passwd_line;	/* struct derived from passwd file line */
238 	uid_t uid;
239 
240 	/*
241 	 * Determine the Linux user identity to re-authenticate.
242 	 * If supported and set, use the login uid, as this should be more stable.
243 	 * Otherwise, use the real uid.
244 	 * The SELinux user identity is no longer used, as Linux users are now
245 	 * mapped to SELinux users via seusers and the SELinux user identity space
246 	 * is separate.
247 	 */
248 #ifdef USE_AUDIT
249 	uid = audit_getloginuid();
250 	if (uid == (uid_t) - 1)
251 		uid = getuid();
252 #else
253 	uid = getuid();
254 #endif
255 
256 	p_passwd_line = getpwuid(uid);
257 	if (!p_passwd_line) {
258 		fprintf(stderr, "cannot find your entry in the passwd file.\n");
259 		return (-1);
260 	}
261 
262 	printf("Authenticating %s.\n", p_passwd_line->pw_name);
263 
264 	/* 
265 	 * Re-authenticate the user running this program.
266 	 * This is just to help confirm user intent (vs. invocation by
267 	 * malicious software), not to authorize the operation (which is covered
268 	 * by policy).  Trusted path mechanism would be preferred.
269 	 */
270 #ifdef USE_PAM
271 	if (!authenticate_via_pam(p_passwd_line)) {
272 #else				/* !USE_PAM */
273 	if (!authenticate_via_shadow_passwd(p_passwd_line)) {
274 #endif				/* if/else USE_PAM */
275 		fprintf(stderr, _("run_init: incorrect password for %s\n"),
276 			p_passwd_line->pw_name);
277 		return (-1);
278 	}
279 
280 	/* If we reach here, then we have authenticated the user. */
281 #ifdef CANTSPELLGDB
282 	printf("You are authenticated!\n");
283 #endif
284 
285 	return 0;
286 
287 }				/* authenticate_user() */
288 
289 /*
290  * get_init_context()
291  *
292  * Get the CONTEXT associated with the context for the init scripts.             *
293  *
294  * in:		nothing
295  * out:		The CONTEXT associated with the context.
296  * return:	0 on success, -1 on failure.
297  */
298 int get_init_context(security_context_t * context)
299 {
300 
301 	FILE *fp;
302 	char buf[255], *bufp;
303 	int buf_len;
304 	char context_file[PATH_MAX];
305 	snprintf(context_file, sizeof(context_file) - 1, "%s/%s",
306 		 selinux_contexts_path(), CONTEXT_FILE);
307 	fp = fopen(context_file, "r");
308 	if (!fp) {
309 		fprintf(stderr, _("Could not open file %s\n"), context_file);
310 		return -1;
311 	}
312 
313 	while (1) {		/* loop until we find a non-empty line */
314 
315 		if (!fgets(buf, sizeof buf, fp))
316 			break;
317 
318 		buf_len = strlen(buf);
319 		if (buf[buf_len - 1] == '\n')
320 			buf[buf_len - 1] = 0;
321 
322 		bufp = buf;
323 		while (*bufp && isspace(*bufp))
324 			bufp++;
325 
326 		if (*bufp) {
327 			*context = strdup(bufp);
328 			if (!(*context))
329 				goto out;
330 			fclose(fp);
331 			return 0;
332 		}
333 	}
334       out:
335 	fclose(fp);
336 	fprintf(stderr, _("No context in file %s\n"), context_file);
337 	return -1;
338 
339 }				/* get_init_context() */
340 
341 /*****************************************************************************
342  * main()                                                                    *
343  *****************************************************************************/
344 int main(int argc, char *argv[])
345 {
346 
347 	extern char *optarg;	/* used by getopt() for arg strings */
348 	extern int opterr;	/* controls getopt() error messages */
349 	security_context_t new_context;	/* context for the init script context  */
350 
351 #ifdef USE_NLS
352 	setlocale(LC_ALL, "");
353 	bindtextdomain(PACKAGE, LOCALEDIR);
354 	textdomain(PACKAGE);
355 #endif
356 
357 	/* Verify that we are running on a flask-enabled kernel. */
358 	if (!is_selinux_enabled()) {
359 		fprintf(stderr,
360 			_
361 			("Sorry, run_init may be used only on a SELinux kernel.\n"));
362 		exit(-1);
363 	}
364 
365 	/*
366 	 * Step 1:  Handle command-line arguments. The first argument is the 
367 	 * name of the script to run. All other arguments are for the script
368 	 * itself, and will be passed directly to the script.
369 	 */
370 
371 	if (argc < 2) {
372 		fprintf(stderr, "%s\n", USAGE_STRING);
373 		exit(-1);
374 	}
375 
376 	/*
377 	 * Step 2:  Authenticate the user.
378 	 */
379 	if (authenticate_user() != 0) {
380 		fprintf(stderr, _("authentication failed.\n"));
381 		exit(-1);
382 	}
383 
384 	/*
385 	 * Step 3: Get the context for the script to be run in.
386 	 */
387 	if (get_init_context(&new_context) == 0) {
388 #ifdef CANTSPELLGDB
389 		printf("context is %s\n", new_context);
390 #endif
391 	} else {
392 		exit(-1);
393 	}
394 
395 	/*
396 	 * Step 4: Run the command in the correct context.
397 	 */
398 
399 	if (chdir("/")) {
400 		perror("chdir");
401 		exit(-1);
402 	}
403 
404 	if (setexeccon(new_context) < 0) {
405 		fprintf(stderr, _("Could not set exec context to %s.\n"),
406 			new_context);
407 		exit(-1);
408 	}
409 	if (! access("/usr/sbin/open_init_pty", X_OK)) {
410 		if (execvp(argv[1], argv + 1)) {
411 			perror("execvp");
412 			exit(-1);
413 		}
414 		return 0;
415 	}
416 	/*
417 	 * Do not execvp the command directly from run_init; since it would run
418 	 * under with a pty under sysadm_devpts_t. Instead, we call open_init_tty,
419 	 * which transitions us into initrc_t, which then spawns a new
420 	 * process, that gets a pty with context initrc_devpts_t. Just
421 	 * execvp or using a exec(1) recycles pty's, and does not open a new
422 	 * one. 
423 	 */
424 	if (execvp("/usr/sbin/open_init_pty", argv)) {
425 		perror("execvp");
426 		exit(-1);
427 	}
428 	return 0;
429 
430 }				/* main() */

policycoreutils-2.1.13/sandbox/seunshare.c

Location Tool Test ID Issue
seunshare.c:271:11 clang-analyzer The left operand to '|' is always 0
seunshare.c:791:0 cppcheck memleakOnRealloc Common realloc mistake: 'pid_table' nulled but not freed upon failure
   1 /*
   2  * Authors: Dan Walsh <dwalsh@redhat.com>
   3  * Authors: Thomas Liu <tliu@fedoraproject.org>
   4  */
   5 
   6 #define _GNU_SOURCE
   7 #include <signal.h>
   8 #include <sys/fsuid.h>
   9 #include <sys/stat.h>
  10 #include <sys/types.h>
  11 #include <sys/wait.h>
  12 #include <syslog.h>
  13 #include <sys/mount.h>
  14 #include <glob.h>
  15 #include <pwd.h>
  16 #include <sched.h>
  17 #include <libcgroup.h>
  18 #include <string.h>
  19 #include <stdio.h>
  20 #include <regex.h>
  21 #include <unistd.h>
  22 #include <stdlib.h>
  23 #include <cap-ng.h>
  24 #include <getopt.h>		/* for getopt_long() form of getopt() */
  25 #include <limits.h>
  26 #include <stdlib.h>
  27 #include <errno.h>
  28 #include <fcntl.h>
  29 
  30 #include <selinux/selinux.h>
  31 #include <selinux/context.h>	/* for context-mangling functions */
  32 #include <dirent.h>
  33 
  34 
  35 /*
  36  * Note setfsuid never returns an error code.  But the compiler complains if 
  37  * I do not check, so I am checking for -1, which should never happen.
  38  */
  39 
  40 #ifdef USE_NLS
  41 #include <locale.h>		/* for setlocale() */
  42 #include <libintl.h>		/* for gettext() */
  43 #define _(msgid) gettext (msgid)
  44 #else
  45 #define _(msgid) (msgid)
  46 #endif
  47 
  48 #ifndef MS_REC
  49 #define MS_REC 1<<14
  50 #endif
  51 
  52 #ifndef MS_SLAVE
  53 #define MS_SLAVE 1<<19
  54 #endif
  55 
  56 #ifndef PACKAGE
  57 #define PACKAGE "policycoreutils"	/* the name of this package lang translation */
  58 #endif
  59 
  60 #define BUF_SIZE 1024
  61 #define DEFAULT_PATH "/usr/bin:/bin"
  62 #define USAGE_STRING _("USAGE: seunshare [ -v ] [ -C ] [ -c ] [ -k ] [ -t tmpdir ] [ -h homedir ] [ -Z CONTEXT ] -- executable [args] ")
  63 
  64 static int verbose = 0;
  65 static int child = 0;
  66 
  67 static capng_select_t cap_set = CAPNG_SELECT_CAPS;
  68 
  69 /**
  70  * This function will drop all capabilities.
  71  */
  72 static int drop_caps()
  73 {
  74 	if (capng_have_capabilities(cap_set) == CAPNG_NONE)
  75 		return 0;
  76 	capng_clear(cap_set);
  77 	if (capng_lock() == -1 || capng_apply(cap_set) == -1) {
  78 		fprintf(stderr, _("Failed to drop all capabilities\n"));
  79 		return -1;
  80 	}
  81 	return 0;
  82 }
  83 
  84 /**
  85  * This function will drop all privileges.
  86  */
  87 static int drop_privs(uid_t uid)
  88 {
  89 	if (drop_caps() == -1 || setresuid(uid, uid, uid) == -1) {
  90 		fprintf(stderr, _("Failed to drop privileges\n"));
  91 		return -1;
  92 	}
  93 	return 0;
  94 }
  95 
  96 /**
  97  * If the user sends a siginto to seunshare, kill the child's session
  98  */
  99 void handler(int sig) {
 100 	if (child > 0) kill(-child,sig);
 101 }
 102 
 103 /**
 104  * Take care of any signal setup.
 105  */
 106 static int set_signal_handles(void)
 107 {
 108 	sigset_t empty;
 109 
 110 	/* Empty the signal mask in case someone is blocking a signal */
 111 	if (sigemptyset(&empty)) {
 112 		fprintf(stderr, "Unable to obtain empty signal set\n");
 113 		return -1;
 114 	}
 115 
 116 	(void)sigprocmask(SIG_SETMASK, &empty, NULL);
 117 
 118 	/* Terminate on SIGHUP */
 119 	if (signal(SIGHUP, SIG_DFL) == SIG_ERR) {
 120 		perror("Unable to set SIGHUP handler");
 121 		return -1;
 122 	}
 123 
 124 	if (signal(SIGINT, handler) == SIG_ERR) {
 125 		perror("Unable to set SIGINT handler");
 126 		return -1;
 127 	}
 128 
 129 	return 0;
 130 }
 131 
 132 #define status_to_retval(status,retval) do { \
 133 	if ((status) == -1) \
 134 		retval = -1; \
 135 	else if (WIFEXITED((status))) \
 136 		retval = WEXITSTATUS((status)); \
 137 	else if (WIFSIGNALED((status))) \
 138 		retval = 128 + WTERMSIG((status)); \
 139 	else \
 140 		retval = -1; \
 141 	} while(0)
 142 
 143 /**
 144  * Spawn external command using system() with dropped privileges.
 145  * TODO: avoid system() and use exec*() instead
 146  */
 147 static int spawn_command(const char *cmd, uid_t uid){
 148 	int child;
 149 	int status = -1;
 150 
 151 	if (verbose > 1)
 152 		printf("spawn_command: %s\n", cmd);
 153 
 154 	child = fork();
 155 	if (child == -1) {
 156 		perror(_("Unable to fork"));
 157 		return status;
 158 	}
 159 
 160 	if (child == 0) {
 161 		if (drop_privs(uid) != 0) exit(-1);
 162 
 163 		status = system(cmd);
 164 		status_to_retval(status, status);
 165 		exit(status);
 166 	}
 167 
 168 	waitpid(child, &status, 0);
 169 	status_to_retval(status, status);
 170 	return status;
 171 }
 172 
 173 /**
 174  * Check file/directory ownership, struct stat * must be passed to the
 175  * functions.
 176  */
 177 static int check_owner_uid(uid_t uid, const char *file, struct stat *st) {
 178 	if (S_ISLNK(st->st_mode)) {
 179 		fprintf(stderr, _("Error: %s must not be a symbolic link\n"), file);
 180 		return -1;
 181 	}
 182 	if (st->st_uid != uid) {
 183 		fprintf(stderr, _("Error: %s not owned by UID %d\n"), file, uid);
 184 		return -1;
 185 	}
 186 	return 0;
 187 }
 188 
 189 static int check_owner_gid(gid_t gid, const char *file, struct stat *st) {
 190 	if (S_ISLNK(st->st_mode)) {
 191 		fprintf(stderr, _("Error: %s must not be a symbolic link\n"), file);
 192 		return -1;
 193 	}
 194 	if (st->st_gid != gid) {
 195 		fprintf(stderr, _("Error: %s not owned by GID %d\n"), file, gid);
 196 		return -1;
 197 	}
 198 	return 0;
 199 }
 200 
 201 #define equal_stats(one,two) \
 202 	((one)->st_dev == (two)->st_dev && (one)->st_ino == (two)->st_ino && \
 203 	 (one)->st_uid == (two)->st_uid && (one)->st_gid == (two)->st_gid && \
 204 	 (one)->st_mode == (two)->st_mode)
 205 
 206 /**
 207  * Sanity check specified directory.  Store stat info for future comparison, or
 208  * compare with previously saved info to detect replaced directories.
 209  * Note: This function does not perform owner checks.
 210  */
 211 static int verify_directory(const char *dir, struct stat *st_in, struct stat *st_out) {
 212 	struct stat sb;
 213 
 214 	if (st_out == NULL) st_out = &sb;
 215 
 216 	if (lstat(dir, st_out) == -1) {
 217 		fprintf(stderr, _("Failed to stat %s: %s\n"), dir, strerror(errno));
 218 		return -1;
 219 	}
 220 	if (! S_ISDIR(st_out->st_mode)) {
 221 		fprintf(stderr, _("Error: %s is not a directory: %s\n"), dir, strerror(errno));
 222 		return -1;
 223 	}
 224 	if (st_in && !equal_stats(st_in, st_out)) {
 225 		fprintf(stderr, _("Error: %s was replaced by a different directory\n"), dir);
 226 		return -1;
 227 	}
 228 
 229 	return 0;
 230 }
 231 
 232 /**
 233  * This function checks to see if the shell is known in /etc/shells.
 234  * If so, it returns 0. On error or illegal shell, it returns -1.
 235  */
 236 static int verify_shell(const char *shell_name)
 237 {
 238 	int rc = -1;
 239 	const char *buf;
 240 
 241 	if (!(shell_name && shell_name[0]))
 242 		return rc;
 243 
 244 	while ((buf = getusershell()) != NULL) {
 245 		/* ignore comments */
 246 		if (*buf == '#')
 247 			continue;
 248 
 249 		/* check the shell skipping newline char */
 250 		if (!strcmp(shell_name, buf)) {
 251 			rc = 0;
 252 			break;
 253 		}
 254 	}
 255 	endusershell();
 256 	return rc;
 257 }
 258 
 259 /**
 260  * Mount directory and check that we mounted the right directory.
 261  */
 262 static int seunshare_mount(const char *src, const char *dst, struct stat *src_st)
 263 {
 264 	int flags = 0;
 265 	int is_tmp = 0;
 266 
 267 	if (verbose)
 268 		printf(_("Mounting %s on %s\n"), src, dst);
 269 
 270 	if (strcmp("/tmp", dst) == 0) {
 271 		flags = flags | MS_NODEV | MS_NOSUID | MS_NOEXEC;
The left operand to '|' is always 0
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

272 is_tmp = 1; 273 } 274 275 /* mount directory */ 276 if (mount(src, dst, NULL, MS_BIND | flags, NULL) < 0) { 277 fprintf(stderr, _("Failed to mount %s on %s: %s\n"), src, dst, strerror(errno)); 278 return -1; 279 } 280 281 /* verify whether we mounted what we expected to mount */ 282 if (verify_directory(dst, src_st, NULL) < 0) return -1; 283 284 /* bind mount /tmp on /var/tmp too */ 285 if (is_tmp) { 286 if (verbose) 287 printf(_("Mounting /tmp on /var/tmp\n")); 288 289 if (mount("/tmp", "/var/tmp", NULL, MS_BIND | flags, NULL) < 0) { 290 fprintf(stderr, _("Failed to mount /tmp on /var/tmp: %s\n"), strerror(errno)); 291 return -1; 292 } 293 } 294 295 return 0; 296 297 } 298 299 /** 300 * Error logging used by cgroups code. 301 */ 302 static int sandbox_error(const char *string) 303 { 304 fprintf(stderr, "%s", string); 305 syslog(LOG_AUTHPRIV | LOG_ALERT, "%s", string); 306 exit(-1); 307 } 308 309 /** 310 * Regular expression match. 311 */ 312 static int match(const char *string, char *pattern) 313 { 314 int status; 315 regex_t re; 316 if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { 317 return 0; 318 } 319 status = regexec(&re, string, (size_t)0, NULL, 0); 320 regfree(&re); 321 if (status != 0) { 322 return 0; 323 } 324 return 1; 325 } 326 327 /** 328 * Apply cgroups settings from the /etc/sysconfig/sandbox config file. 329 */ 330 static int setup_cgroups() 331 { 332 char *cpus = NULL; /* which CPUs to use */ 333 char *cgroupname = NULL;/* name for the cgroup */ 334 char *mem = NULL; /* string for memory amount to pass to cgroup */ 335 int64_t memusage = 0; /* amount of memory to use max (percent) */ 336 int cpupercentage = 0; /* what percentage of cpu to allow usage */ 337 FILE* fp; 338 char buf[BUF_SIZE]; 339 char *tok = NULL; 340 int rc = -1; 341 char *str = NULL; 342 const char* fname = "/etc/sysconfig/sandbox"; 343 344 if ((fp = fopen(fname, "rt")) == NULL) { 345 fprintf(stderr, "Error opening sandbox config file."); 346 return rc; 347 } 348 while(fgets(buf, BUF_SIZE, fp) != NULL) { 349 /* Skip comments */ 350 if (buf[0] == '#') continue; 351 352 /* Copy the string, ignoring whitespace */ 353 int len = strlen(buf); 354 free(str); 355 str = malloc((len + 1) * sizeof(char)); 356 if (!str) 357 goto err; 358 359 int ind = 0; 360 int i; 361 for (i = 0; i < len; i++) { 362 char cur = buf[i]; 363 if (cur != ' ' && cur != '\t') { 364 str[ind] = cur; 365 ind++; 366 } 367 } 368 str[ind] = '\0'; 369 370 tok = strtok(str, "=\n"); 371 if (tok != NULL) { 372 if (!strcmp(tok, "CPUAFFINITY")) { 373 tok = strtok(NULL, "=\n"); 374 cpus = strdup(tok); 375 if (!strcmp(cpus, "ALL")) { 376 free(cpus); 377 cpus = NULL; 378 } 379 } else if (!strcmp(tok, "MEMUSAGE")) { 380 tok = strtok(NULL, "=\n"); 381 if (match(tok, "^[0-9]+[kKmMgG%]")) { 382 char *ind = strchr(tok, '%'); 383 if (ind != NULL) { 384 *ind = '\0';; 385 memusage = atoi(tok); 386 } else { 387 mem = strdup(tok); 388 } 389 } else { 390 fprintf(stderr, "Error parsing config file."); 391 goto err; 392 } 393 394 } else if (!strcmp(tok, "CPUUSAGE")) { 395 tok = strtok(NULL, "=\n"); 396 if (match(tok, "^[0-9]+\%")) { 397 char* ind = strchr(tok, '%'); 398 *ind = '\0'; 399 cpupercentage = atoi(tok); 400 } else { 401 fprintf(stderr, "Error parsing config file."); 402 goto err; 403 } 404 } else if (!strcmp(tok, "NAME")) { 405 tok = strtok(NULL, "=\n"); 406 cgroupname = strdup(tok); 407 } else { 408 continue; 409 } 410 } 411 412 } 413 if (mem == NULL) { 414 long phypz = sysconf(_SC_PHYS_PAGES); 415 long psize = sysconf(_SC_PAGE_SIZE); 416 memusage = phypz * psize * (float) memusage / 100.0; 417 } 418 419 cgroup_init(); 420 421 int64_t current_runtime = 0; 422 int64_t current_period = 0 ; 423 int64_t current_mem = 0; 424 char *curr_cpu_path = NULL; 425 char *curr_mem_path = NULL; 426 int ret = cgroup_get_current_controller_path(getpid(), "cpu", &curr_cpu_path); 427 if (ret) { 428 sandbox_error("Error while trying to get current controller path.\n"); 429 } else { 430 struct cgroup *curr = cgroup_new_cgroup(curr_cpu_path); 431 cgroup_get_cgroup(curr); 432 cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_runtime_us", &current_runtime); 433 cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_period_us", &current_period); 434 } 435 436 ret = cgroup_get_current_controller_path(getpid(), "memory", &curr_mem_path); 437 if (ret) { 438 sandbox_error("Error while trying to get current controller path.\n"); 439 } else { 440 struct cgroup *curr = cgroup_new_cgroup(curr_mem_path); 441 cgroup_get_cgroup(curr); 442 cgroup_get_value_int64(cgroup_get_controller(curr, "memory"), "memory.limit_in_bytes", &current_mem); 443 } 444 445 if (((float) cpupercentage) / 100.0> (float)current_runtime / (float) current_period) { 446 sandbox_error("CPU usage restricted!\n"); 447 goto err; 448 } 449 450 if (mem == NULL) { 451 if (memusage > current_mem) { 452 sandbox_error("Attempting to use more memory than allowed!"); 453 goto err; 454 } 455 } 456 457 long nprocs = sysconf(_SC_NPROCESSORS_ONLN); 458 459 struct sched_param sp; 460 sp.sched_priority = sched_get_priority_min(SCHED_FIFO); 461 sched_setscheduler(getpid(), SCHED_FIFO, &sp); 462 struct cgroup *sandbox_group = cgroup_new_cgroup(cgroupname); 463 cgroup_add_controller(sandbox_group, "memory"); 464 cgroup_add_controller(sandbox_group, "cpu"); 465 466 if (mem == NULL) { 467 if (memusage > 0) { 468 cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", memusage); 469 } 470 } else { 471 cgroup_set_value_string(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", mem); 472 } 473 if (cpupercentage > 0) { 474 cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "cpu"), "cpu.rt_runtime_us", 475 (float) cpupercentage / 100.0 * 60000); 476 cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "cpu"), "cpu.rt_period_us",60000 * nprocs); 477 } 478 if (cpus != NULL) { 479 cgroup_set_value_string(cgroup_get_controller(sandbox_group, "cpu"), "cgroup.procs",cpus); 480 } 481 482 uint64_t allocated_mem; 483 if (cgroup_get_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", &allocated_mem) > current_mem) { 484 sandbox_error("Attempting to use more memory than allowed!\n"); 485 goto err; 486 } 487 488 rc = cgroup_create_cgroup(sandbox_group, 1); 489 if (rc != 0) { 490 sandbox_error("Failed to create group. Ensure that cgconfig service is running. \n"); 491 goto err; 492 } 493 494 cgroup_attach_task(sandbox_group); 495 496 rc = 0; 497 err: 498 fclose(fp); 499 free(str); 500 free(mem); 501 free(cgroupname); 502 free(cpus); 503 return rc; 504 } 505 506 /* 507 If path is empy or ends with "/." or "/.. return -1 else return 0; 508 */ 509 static int bad_path(const char *path) { 510 const char *ptr; 511 ptr = path; 512 while (*ptr) ptr++; 513 if (ptr == path) return -1; // ptr null 514 ptr--; 515 if (ptr != path && *ptr == '.') { 516 ptr--; 517 if (*ptr == '/') return -1; // path ends in /. 518 if (*ptr == '.') { 519 if (ptr != path) { 520 ptr--; 521 if (*ptr == '/') return -1; // path ends in /.. 522 } 523 } 524 } 525 return 0; 526 } 527 528 static int rsynccmd(const char * src, const char *dst, char **cmdbuf) 529 { 530 char *buf = NULL; 531 char *newbuf = NULL; 532 glob_t fglob; 533 fglob.gl_offs = 0; 534 int flags = GLOB_PERIOD; 535 unsigned int i = 0; 536 int rc = -1; 537 538 /* match glob for all files in src dir */ 539 if (asprintf(&buf, "%s/*", src) == -1) { 540 fprintf(stderr, "Out of memory\n"); 541 return -1; 542 } 543 544 if (glob(buf, flags, NULL, &fglob) != 0) { 545 free(buf); buf = NULL; 546 return -1; 547 } 548 549 free(buf); buf = NULL; 550 551 for ( i=0; i < fglob.gl_pathc; i++) { 552 const char *path = fglob.gl_pathv[i]; 553 554 if (bad_path(path)) continue; 555 556 if (!buf) { 557 if (asprintf(&newbuf, "\'%s\'", path) == -1) { 558 fprintf(stderr, "Out of memory\n"); 559 goto err; 560 } 561 } else { 562 if (asprintf(&newbuf, "%s \'%s\'", buf, path) == -1) { 563 fprintf(stderr, "Out of memory\n"); 564 goto err; 565 } 566 } 567 568 free(buf); buf = newbuf; 569 newbuf = NULL; 570 } 571 572 if (buf) { 573 if (asprintf(&newbuf, "/usr/bin/rsync -trlHDq %s '%s'", buf, dst) == -1) { 574 fprintf(stderr, "Out of memory\n"); 575 goto err; 576 } 577 *cmdbuf=newbuf; 578 } 579 else { 580 *cmdbuf=NULL; 581 } 582 rc = 0; 583 584 err: 585 free(buf); buf = NULL; 586 globfree(&fglob); 587 return rc; 588 } 589 590 /** 591 * Clean up runtime temporary directory. Returns 0 if no problem was detected, 592 * >0 if some error was detected, but errors here are treated as non-fatal and 593 * left to tmpwatch to finish incomplete cleanup. 594 */ 595 static int cleanup_tmpdir(const char *tmpdir, const char *src, 596 struct passwd *pwd, int copy_content) 597 { 598 char *cmdbuf = NULL; 599 int rc = 0; 600 601 /* rsync files back */ 602 if (copy_content) { 603 if (asprintf(&cmdbuf, "/usr/bin/rsync --exclude=.X11-unix -utrlHDq --delete '%s/' '%s/'", tmpdir, src) == -1) { 604 fprintf(stderr, _("Out of memory\n")); 605 cmdbuf = NULL; 606 rc++; 607 } 608 if (cmdbuf && spawn_command(cmdbuf, pwd->pw_uid) != 0) { 609 fprintf(stderr, _("Failed to copy files from the runtime temporary directory\n")); 610 rc++; 611 } 612 free(cmdbuf); cmdbuf = NULL; 613 } 614 615 /* remove files from the runtime temporary directory */ 616 if (asprintf(&cmdbuf, "/bin/rm -r '%s/' 2>/dev/null", tmpdir) == -1) { 617 fprintf(stderr, _("Out of memory\n")); 618 cmdbuf = NULL; 619 rc++; 620 } 621 /* this may fail if there's root-owned file left in the runtime tmpdir */ 622 if (cmdbuf && spawn_command(cmdbuf, pwd->pw_uid) != 0) rc++; 623 free(cmdbuf); cmdbuf = NULL; 624 625 /* remove runtime temporary directory */ 626 if (setfsuid(0) < 0) 627 rc++; 628 629 if (rmdir(tmpdir) == -1) 630 fprintf(stderr, _("Failed to remove directory %s: %s\n"), tmpdir, strerror(errno)); 631 if (setfsuid(pwd->pw_uid) < 0) 632 rc++; 633 634 return rc; 635 } 636 637 /** 638 * seunshare will create a tmpdir in /tmp, with root ownership. The parent 639 * process waits for it child to exit to attempt to remove the directory. If 640 * it fails to remove the directory, we will need to rely on tmpreaper/tmpwatch 641 * to clean it up. 642 */ 643 static char *create_tmpdir(const char *src, struct stat *src_st, 644 struct stat *out_st, struct passwd *pwd, security_context_t execcon) 645 { 646 char *tmpdir = NULL; 647 char *cmdbuf = NULL; 648 int fd_t = -1, fd_s = -1; 649 struct stat tmp_st; 650 security_context_t con = NULL; 651 652 /* get selinux context */ 653 if (execcon) { 654 if (setfsuid(pwd->pw_uid) < 0) 655 goto err; 656 657 if ((fd_s = open(src, O_RDONLY)) < 0) { 658 fprintf(stderr, _("Failed to open directory %s: %s\n"), src, strerror(errno)); 659 goto err; 660 } 661 if (fstat(fd_s, &tmp_st) == -1) { 662 fprintf(stderr, _("Failed to stat directory %s: %s\n"), src, strerror(errno)); 663 goto err; 664 } 665 if (!equal_stats(src_st, &tmp_st)) { 666 fprintf(stderr, _("Error: %s was replaced by a different directory\n"), src); 667 goto err; 668 } 669 if (fgetfilecon(fd_s, &con) == -1) { 670 fprintf(stderr, _("Failed to get context of the directory %s: %s\n"), src, strerror(errno)); 671 goto err; 672 } 673 674 /* ok to not reach this if there is an error */ 675 if (setfsuid(0) < 0) 676 goto err; 677 } 678 679 if (asprintf(&tmpdir, "/tmp/.sandbox-%s-XXXXXX", pwd->pw_name) == -1) { 680 fprintf(stderr, _("Out of memory\n")); 681 tmpdir = NULL; 682 goto err; 683 } 684 if (mkdtemp(tmpdir) == NULL) { 685 fprintf(stderr, _("Failed to create temporary directory: %s\n"), strerror(errno)); 686 goto err; 687 } 688 689 /* temporary directory must be owned by root:user */ 690 if (verify_directory(tmpdir, NULL, out_st) < 0) { 691 goto err; 692 } 693 694 if (check_owner_uid(0, tmpdir, out_st) < 0) 695 goto err; 696 697 if (check_owner_gid(getgid(), tmpdir, out_st) < 0) 698 goto err; 699 700 /* change permissions of the temporary directory */ 701 if ((fd_t = open(tmpdir, O_RDONLY)) < 0) { 702 fprintf(stderr, _("Failed to open directory %s: %s\n"), tmpdir, strerror(errno)); 703 goto err; 704 } 705 if (fstat(fd_t, &tmp_st) == -1) { 706 fprintf(stderr, _("Failed to stat directory %s: %s\n"), tmpdir, strerror(errno)); 707 goto err; 708 } 709 if (!equal_stats(out_st, &tmp_st)) { 710 fprintf(stderr, _("Error: %s was replaced by a different directory\n"), tmpdir); 711 goto err; 712 } 713 if (fchmod(fd_t, 01770) == -1) { 714 fprintf(stderr, _("Unable to change mode on %s: %s\n"), tmpdir, strerror(errno)); 715 goto err; 716 } 717 /* re-stat again to pick change mode */ 718 if (fstat(fd_t, out_st) == -1) { 719 fprintf(stderr, _("Failed to stat directory %s: %s\n"), tmpdir, strerror(errno)); 720 goto err; 721 } 722 723 /* copy selinux context */ 724 if (execcon) { 725 if (fsetfilecon(fd_t, con) == -1) { 726 fprintf(stderr, _("Failed to set context of the directory %s: %s\n"), tmpdir, strerror(errno)); 727 goto err; 728 } 729 } 730 731 if (setfsuid(pwd->pw_uid) < 0) 732 goto err; 733 734 if (rsynccmd(src, tmpdir, &cmdbuf) < 0) { 735 goto err; 736 } 737 738 /* ok to not reach this if there is an error */ 739 if (setfsuid(0) < 0) 740 goto err; 741 742 if (cmdbuf && spawn_command(cmdbuf, pwd->pw_uid) != 0) { 743 fprintf(stderr, _("Failed to populate runtime temporary directory\n")); 744 cleanup_tmpdir(tmpdir, src, pwd, 0); 745 goto err; 746 } 747 748 goto good; 749 err: 750 free(tmpdir); tmpdir = NULL; 751 good: 752 free(cmdbuf); cmdbuf = NULL; 753 freecon(con); con = NULL; 754 if (fd_t >= 0) close(fd_t); 755 if (fd_s >= 0) close(fd_s); 756 return tmpdir; 757 } 758 759 #define PROC_BASE "/proc" 760 761 static int 762 killall (security_context_t execcon) 763 { 764 DIR *dir; 765 security_context_t scon; 766 struct dirent *de; 767 pid_t *pid_table, pid, self; 768 int i; 769 int pids, max_pids; 770 int running = 0; 771 self = getpid(); 772 if (!(dir = opendir(PROC_BASE))) { 773 return -1; 774 } 775 max_pids = 256; 776 pid_table = malloc(max_pids * sizeof (pid_t)); 777 if (!pid_table) { 778 (void)closedir(dir); 779 return -1; 780 } 781 pids = 0; 782 context_t con; 783 con = context_new(execcon); 784 const char *mcs = context_range_get(con); 785 printf("mcs=%s\n", mcs); 786 while ((de = readdir (dir)) != NULL) { 787 if (!(pid = (pid_t)atoi(de->d_name)) || pid == self) 788 continue; 789 790 if (pids == max_pids) { 791 if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
Common realloc mistake: 'pid_table' nulled but not freed upon failure
(emitted by cppcheck)
792 (void)closedir(dir); 793 return -1; 794 } 795 max_pids *= 2; 796 } 797 pid_table[pids++] = pid; 798 } 799 800 (void)closedir(dir); 801 802 for (i = 0; i < pids; i++) { 803 pid_t id = pid_table[i]; 804 805 if (getpidcon(id, &scon) == 0) { 806 807 context_t pidcon = context_new(scon); 808 /* Attempt to kill remaining processes */ 809 if (strcmp(context_range_get(pidcon), mcs) == 0) 810 kill(id, SIGKILL); 811 812 context_free(pidcon); 813 freecon(scon); 814 } 815 running++; 816 } 817 818 context_free(con); 819 free(pid_table); 820 return running; 821 } 822 823 int main(int argc, char **argv) { 824 int status = -1; 825 security_context_t execcon = NULL; 826 827 int clflag; /* holds codes for command line flags */ 828 int usecgroups = 0; 829 int kill_all = 0; 830 831 char *homedir_s = NULL; /* homedir spec'd by user in argv[] */ 832 char *tmpdir_s = NULL; /* tmpdir spec'd by user in argv[] */ 833 char *tmpdir_r = NULL; /* tmpdir created by seunshare */ 834 835 struct stat st_homedir; 836 struct stat st_tmpdir_s; 837 struct stat st_tmpdir_r; 838 839 const struct option long_options[] = { 840 {"homedir", 1, 0, 'h'}, 841 {"tmpdir", 1, 0, 't'}, 842 {"kill", 1, 0, 'k'}, 843 {"verbose", 1, 0, 'v'}, 844 {"cgroups", 1, 0, 'c'}, 845 {"context", 1, 0, 'Z'}, 846 {"capabilities", 1, 0, 'C'}, 847 {NULL, 0, 0, 0} 848 }; 849 850 uid_t uid = getuid(); 851 /* 852 if (!uid) { 853 fprintf(stderr, _("Must not be root")); 854 return -1; 855 } 856 */ 857 858 #ifdef USE_NLS 859 setlocale(LC_ALL, ""); 860 bindtextdomain(PACKAGE, LOCALEDIR); 861 textdomain(PACKAGE); 862 #endif 863 864 struct passwd *pwd=getpwuid(uid); 865 if (!pwd) { 866 perror(_("getpwduid failed")); 867 return -1; 868 } 869 870 if (verify_shell(pwd->pw_shell) < 0) { 871 fprintf(stderr, _("Error: User shell is not valid\n")); 872 return -1; 873 } 874 875 while (1) { 876 clflag = getopt_long(argc, argv, "Ccvh:t:Z:", long_options, NULL); 877 if (clflag == -1) 878 break; 879 880 switch (clflag) { 881 case 't': 882 tmpdir_s = optarg; 883 break; 884 case 'k': 885 kill_all = 1; 886 break; 887 case 'h': 888 homedir_s = optarg; 889 break; 890 case 'v': 891 verbose++; 892 break; 893 case 'c': 894 usecgroups = 1; 895 break; 896 case 'C': 897 cap_set = CAPNG_SELECT_CAPS; 898 break; 899 case 'Z': 900 execcon = optarg; 901 break; 902 default: 903 fprintf(stderr, "%s\n", USAGE_STRING); 904 return -1; 905 } 906 } 907 908 if (! homedir_s && ! tmpdir_s) { 909 fprintf(stderr, _("Error: tmpdir and/or homedir required\n %s\n"), USAGE_STRING); 910 return -1; 911 } 912 913 if (argc - optind < 1) { 914 fprintf(stderr, _("Error: executable required\n %s\n"), USAGE_STRING); 915 return -1; 916 } 917 918 if (execcon && is_selinux_enabled() != 1) { 919 fprintf(stderr, _("Error: execution context specified, but SELinux is not enabled\n")); 920 return -1; 921 } 922 923 if (set_signal_handles()) 924 return -1; 925 926 if (usecgroups && setup_cgroups() < 0) 927 return -1; 928 929 /* set fsuid to ruid */ 930 /* Changing fsuid is usually required when user-specified directory is 931 * on an NFS mount. It's also desired to avoid leaking info about 932 * existence of the files not accessible to the user. */ 933 if (setfsuid(uid) < 0) 934 return -1; 935 936 /* verify homedir and tmpdir */ 937 if (homedir_s && ( 938 verify_directory(homedir_s, NULL, &st_homedir) < 0 || 939 check_owner_uid(uid, homedir_s, &st_homedir))) return -1; 940 if (tmpdir_s && ( 941 verify_directory(tmpdir_s, NULL, &st_tmpdir_s) < 0 || 942 check_owner_uid(uid, tmpdir_s, &st_tmpdir_s))) return -1; 943 if (setfsuid(0) < 0) return -1; 944 945 /* create runtime tmpdir */ 946 if (tmpdir_s && (tmpdir_r = create_tmpdir(tmpdir_s, &st_tmpdir_s, 947 &st_tmpdir_r, pwd, execcon)) == NULL) { 948 fprintf(stderr, _("Failed to create runtime temporary directory\n")); 949 return -1; 950 } 951 952 /* spawn child process */ 953 child = fork(); 954 if (child == -1) { 955 perror(_("Unable to fork")); 956 goto err; 957 } 958 959 if (child == 0) { 960 char *display = NULL; 961 char *LANG = NULL; 962 int rc = -1; 963 964 if (unshare(CLONE_NEWNS) < 0) { 965 perror(_("Failed to unshare")); 966 goto childerr; 967 } 968 969 /* Remount / as SLAVE so that nothing mounted in the namespace 970 shows up in the parent */ 971 if (mount("none", "/", NULL, MS_SLAVE | MS_REC , NULL) < 0) { 972 perror(_("Failed to make / a SLAVE mountpoint\n")); 973 goto childerr; 974 } 975 976 /* assume fsuid==ruid after this point */ 977 if (setfsuid(uid) < 0) goto childerr; 978 979 /* mount homedir and tmpdir, in this order */ 980 if (homedir_s && seunshare_mount(homedir_s, pwd->pw_dir, 981 &st_homedir) != 0) goto childerr; 982 if (tmpdir_s && seunshare_mount(tmpdir_r, "/tmp", 983 &st_tmpdir_r) != 0) goto childerr; 984 985 if (drop_privs(uid) != 0) goto childerr; 986 987 /* construct a new environment */ 988 if ((display = getenv("DISPLAY")) != NULL) { 989 if ((display = strdup(display)) == NULL) { 990 perror(_("Out of memory")); 991 goto childerr; 992 } 993 } 994 995 /* construct a new environment */ 996 if ((LANG = getenv("LANG")) != NULL) { 997 if ((LANG = strdup(LANG)) == NULL) { 998 perror(_("Out of memory")); 999 goto childerr; 1000 } 1001 } 1002 1003 if ((rc = clearenv()) != 0) { 1004 perror(_("Failed to clear environment")); 1005 goto childerr; 1006 } 1007 if (display) 1008 rc |= setenv("DISPLAY", display, 1); 1009 if (LANG) 1010 rc |= setenv("LANG", LANG, 1); 1011 rc |= setenv("HOME", pwd->pw_dir, 1); 1012 rc |= setenv("SHELL", pwd->pw_shell, 1); 1013 rc |= setenv("USER", pwd->pw_name, 1); 1014 rc |= setenv("LOGNAME", pwd->pw_name, 1); 1015 rc |= setenv("PATH", DEFAULT_PATH, 1); 1016 if (rc != 0) { 1017 fprintf(stderr, _("Failed to construct environment\n")); 1018 goto childerr; 1019 } 1020 1021 /* selinux context */ 1022 if (execcon && setexeccon(execcon) != 0) { 1023 fprintf(stderr, _("Could not set exec context to %s. %s\n"), execcon, strerror(errno)); 1024 goto childerr; 1025 } 1026 1027 if (chdir(pwd->pw_dir)) { 1028 perror(_("Failed to change dir to homedir")); 1029 goto childerr; 1030 } 1031 setsid(); 1032 execv(argv[optind], argv + optind); 1033 fprintf(stderr, _("Failed to execute command %s: %s\n"), argv[optind], strerror(errno)); 1034 childerr: 1035 free(display); 1036 free(LANG); 1037 exit(-1); 1038 } 1039 1040 drop_caps(); 1041 1042 /* parent waits for child exit to do the cleanup */ 1043 waitpid(child, &status, 0); 1044 status_to_retval(status, status); 1045 1046 /* Make sure all child processes exit */ 1047 kill(-child,SIGTERM); 1048 1049 if (execcon && kill_all) 1050 killall(execcon); 1051 1052 if (tmpdir_r) cleanup_tmpdir(tmpdir_r, tmpdir_s, pwd, 1); 1053 1054 err: 1055 free(tmpdir_r); 1056 return status; 1057 }

policycoreutils-2.1.13/secon/secon.c

No issues found

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <assert.h>
  4 
  5 #include <string.h>
  6 
  7 #define xstreq(x, y) !strcmp(x, y)
  8 
  9 #include <err.h>
 10 
 11 #include <getopt.h>
 12 #include <sys/types.h>
 13 #include <unistd.h>
 14 #include <selinux/selinux.h>
 15 #include <selinux/context.h>
 16 
 17 #define TRUE  1
 18 #define FALSE 0
 19 
 20 #define SECON_CONF_PROG_NAME "secon"	/* default program name */
 21 #define SECON_OPTS_SM "hVurtscmPRfLp"	/* small options available, print */
 22 #define SECON_OPTS_GO "hVurtlscmPRf:L:p:"	/* small options available, getopt */
 23 
 24 #define OPTS_FROM_ARG      0
 25 #define OPTS_FROM_FILE     1
 26 #define OPTS_FROM_LINK     2
 27 #define OPTS_FROM_STDIN    3
 28 #define OPTS_FROM_CUR      4
 29 #define OPTS_FROM_CUREXE   5
 30 #define OPTS_FROM_CURFS    6
 31 #define OPTS_FROM_CURKEY   7
 32 #define OPTS_FROM_PROC     8
 33 #define OPTS_FROM_PROCEXE  9
 34 #define OPTS_FROM_PROCFS   10
 35 #define OPTS_FROM_PROCKEY  11
 36 
 37 struct {
 38 	unsigned int disp_user:1;
 39 	unsigned int disp_role:1;
 40 	unsigned int disp_type:1;
 41 	unsigned int disp_sen:1;
 42 	unsigned int disp_clr:1;
 43 	unsigned int disp_mlsr:1;
 44 
 45 	unsigned int disp_raw:1;
 46 
 47 	unsigned int disp_prompt:1;	/* no return, use : to sep */
 48 
 49 	unsigned int from_type:8;	/* 16 bits, uses 4 bits */
 50 
 51 	union {
 52 		pid_t pid;
 53 		const char *file;
 54 		const char *link;
 55 		const char *arg;
 56 	} f;
 57 } opts[1] = { {
 58 		FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
 59 		    FALSE, FALSE, OPTS_FROM_ARG, {
 60 0}}};
 61 
 62 static void usage(const char *name, int exit_code)
 63 {
 64 	fprintf(exit_code ? stderr : stdout,
 65 		"  Usage: %s [-%s] [ context | - ]\n"
 66 		"          --help        -h     Show this message.\n"
 67 		"          --version     -V     Show the version.\n"
 68 		"          --prompt      -P     Output in a format good for a prompt.\n"
 69 		"          --user        -u     Show the user of the context.\n"
 70 		"          --role        -r     Show the role of the context.\n"
 71 		"          --type        -t     Show the type of the context.\n"
 72 		"          --sensitivity -s     Show the sensitivity level of the context.\n"
 73 		"          --clearance   -c     Show the clearance level of the context.\n"
 74 		"          --mls-range   -m     Show the sensitivity to clearance range of \n"
 75 		"                               the context.\n"
 76 		"          --raw         -R     Show the context in \"raw\" format.\n"
 77 		"          --current            Get the context for the current process.\n"
 78 		"          --self               Get the context for the current process.\n"
 79 		"          --self-exec          Get the exec context for the current process.\n"
 80 		"          --self-fs            Get the fs context for the current process.\n"
 81 		"          --self-key           Get the key context for the current process.\n"
 82 		"          --parent             Get the context for the parent process.\n"
 83 		"          --parent-exec        Get the exec context for the parent process.\n"
 84 		"          --parent-fs          Get the fs context for the parent process.\n"
 85 		"          --parent-key         Get the key context for the parent process.\n"
 86 		"          --pid       -p <arg> Use the context from the specified pid.\n"
 87 		"          --pid-exec     <arg> Use the exec context from the specified pid.\n"
 88 		"          --pid-fs       <arg> Use the fs context from the specified pid.\n"
 89 		"          --pid-key      <arg> Use the key context from the specified pid.\n"
 90 		"          --file      -f <arg> Use the context from the specified file.\n"
 91 		"          --link      -L <arg> Use the context from the specified link.\n",
 92 		name, SECON_OPTS_SM);
 93 
 94 	exit(exit_code);
 95 }
 96 
 97 static const char *opt_program_name(const char *argv0, const char *def)
 98 {
 99 	if (argv0) {
100 		if ((def = strrchr(argv0, '/')))
101 			++def;
102 		else
103 			def = argv0;
104 
105 		/* hack for libtool */
106 		if ((strlen(def) > strlen("lt-"))
107 		    && !memcmp("lt-", def, strlen("lt-")))
108 			def += 3;
109 	}
110 
111 	return (def);
112 }
113 
114 static int disp_num(void)
115 {
116 	int num = 0;
117 
118 	num += opts->disp_user;
119 	num += opts->disp_role;
120 	num += opts->disp_type;
121 	num += opts->disp_sen;
122 	num += opts->disp_clr;
123 	num += opts->disp_mlsr;
124 
125 	return (num);
126 }
127 
128 static int disp_none(void)
129 {
130 	return (!disp_num());
131 }
132 
133 static int disp_multi(void)
134 {
135 	return (disp_num() > 1);
136 }
137 
138 static void cmd_line(int argc, char *argv[])
139 {
140 	int optchar = 0;
141 	const char *program_name = NULL;
142 	struct option long_options[] = {
143 		{"help", no_argument, NULL, 'h'},
144 		{"version", no_argument, NULL, 'V'},
145 
146 		{"prompt", no_argument, NULL, 'P'},
147 
148 		{"user", no_argument, NULL, 'u'},
149 		{"role", no_argument, NULL, 'r'},
150 		{"type", no_argument, NULL, 't'},
151 		{"level", no_argument, NULL, 'l'},	/* compat. */
152 		{"sensitivity", no_argument, NULL, 's'},
153 		{"range", no_argument, NULL, 'm'},
154 		{"clearance", no_argument, NULL, 'c'},
155 		{"mls-range", no_argument, NULL, 'm'},
156 
157 		{"raw", no_argument, NULL, 'R'},
158 
159 		{"current", no_argument, NULL, 1},
160 		{"self", no_argument, NULL, 1},
161 		{"current-exec", no_argument, NULL, 2},
162 		{"self-exec", no_argument, NULL, 2},
163 		{"current-fs", no_argument, NULL, 3},
164 		{"self-fs", no_argument, NULL, 3},
165 		{"current-key", no_argument, NULL, 4},
166 		{"self-key", no_argument, NULL, 4},
167 
168 		{"parent", no_argument, NULL, 5},
169 		{"parent-exec", no_argument, NULL, 6},
170 		{"parent-fs", no_argument, NULL, 7},
171 		{"parent-key", no_argument, NULL, 8},
172 
173 		{"file", required_argument, NULL, 'f'},
174 		{"link", required_argument, NULL, 'L'},
175 		{"pid", required_argument, NULL, 'p'},
176 		{"pid-exec", required_argument, NULL, 9},
177 		{"pid-fs", required_argument, NULL, 10},
178 		{"pid-key", required_argument, NULL, 11},
179 
180 		{NULL, 0, NULL, 0}
181 	};
182 	int done = FALSE;
183 
184 	program_name = opt_program_name(argv[0], SECON_CONF_PROG_NAME);
185 
186 	while ((optchar = getopt_long(argc, argv, SECON_OPTS_GO,
187 				      long_options, NULL)) != -1) {
188 		switch (optchar) {
189 		case '?':
190 			usage(program_name, EXIT_FAILURE);
191 		case 'h':
192 			usage(program_name, EXIT_SUCCESS);
193 		case 'V':
194 			fprintf(stdout,
195 				" %s version %s.\n", program_name, VERSION);
196 			exit(EXIT_SUCCESS);
197 
198 		case 'u':
199 			done = TRUE;
200 			opts->disp_user = !opts->disp_user;
201 			break;
202 		case 'r':
203 			done = TRUE;
204 			opts->disp_role = !opts->disp_role;
205 			break;
206 		case 't':
207 			done = TRUE;
208 			opts->disp_type = !opts->disp_type;
209 			break;
210 		case 'l':
211 			done = TRUE;
212 			opts->disp_sen = !opts->disp_sen;
213 			break;
214 		case 's':
215 			done = TRUE;
216 			opts->disp_sen = !opts->disp_sen;
217 			break;
218 		case 'c':
219 			done = TRUE;
220 			opts->disp_clr = !opts->disp_clr;
221 			break;
222 		case 'm':
223 			done = TRUE;
224 			opts->disp_mlsr = !opts->disp_mlsr;
225 			break;
226 
227 		case 'P':
228 			opts->disp_prompt = !opts->disp_prompt;
229 			break;
230 
231 		case 'R':
232 			opts->disp_raw = !opts->disp_raw;
233 			break;
234 		case 1:
235 			opts->from_type = OPTS_FROM_CUR;
236 			break;
237 		case 2:
238 			opts->from_type = OPTS_FROM_CUREXE;
239 			break;
240 		case 3:
241 			opts->from_type = OPTS_FROM_CURFS;
242 			break;
243 		case 4:
244 			opts->from_type = OPTS_FROM_CURKEY;
245 			break;
246 
247 		case 5:
248 			opts->from_type = OPTS_FROM_PROC;
249 			opts->f.pid = getppid();
250 			break;
251 		case 6:
252 			opts->from_type = OPTS_FROM_PROCEXE;
253 			opts->f.pid = getppid();
254 			break;
255 		case 7:
256 			opts->from_type = OPTS_FROM_PROCFS;
257 			opts->f.pid = getppid();
258 			break;
259 		case 8:
260 			opts->from_type = OPTS_FROM_PROCKEY;
261 			opts->f.pid = getppid();
262 			break;
263 
264 		case 'f':
265 			opts->from_type = OPTS_FROM_FILE;
266 			opts->f.file = optarg;
267 			break;
268 		case 'L':
269 			opts->from_type = OPTS_FROM_LINK;
270 			opts->f.link = optarg;
271 			break;
272 		case 'p':
273 			opts->from_type = OPTS_FROM_PROC;
274 			opts->f.pid = atoi(optarg);
275 			break;
276 		case 9:
277 			opts->from_type = OPTS_FROM_PROCEXE;
278 			opts->f.pid = atoi(optarg);
279 			break;
280 		case 10:
281 			opts->from_type = OPTS_FROM_PROCFS;
282 			opts->f.pid = atoi(optarg);
283 			break;
284 		case 11:
285 			opts->from_type = OPTS_FROM_PROCKEY;
286 			opts->f.pid = atoi(optarg);
287 			break;
288 
289 		default:
290 			assert(FALSE);
291 		}
292 	}
293 
294 	if (!done) {		/* defualt, if nothing specified */
295 		opts->disp_user = TRUE;
296 		opts->disp_role = TRUE;
297 		opts->disp_type = TRUE;
298 		if (!opts->disp_prompt) {	/* when displaying prompt, just output "normal" by default */
299 			opts->disp_sen = TRUE;
300 			opts->disp_clr = TRUE;
301 		}
302 		opts->disp_mlsr = TRUE;
303 	}
304 
305 	if (disp_none())
306 		err(EXIT_FAILURE, " Nothing to display");
307 
308 	argc -= optind;
309 	argv += optind;
310 
311 	if (!argc && (opts->from_type == OPTS_FROM_ARG)
312 	    && !isatty(STDIN_FILENO))
313 		opts->from_type = OPTS_FROM_STDIN;
314 	if (!argc && (opts->from_type == OPTS_FROM_ARG))
315 		opts->from_type = OPTS_FROM_CUR;
316 
317 	if (opts->from_type == OPTS_FROM_ARG) {
318 		opts->f.arg = argv[0];
319 
320 		if (xstreq(argv[0], "-"))
321 			opts->from_type = OPTS_FROM_STDIN;
322 	} else if (!is_selinux_enabled())
323 		errx(EXIT_FAILURE, "SELinux is not enabled");
324 }
325 
326 static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
327 {
328 	char buf[4096];
329 	FILE *fp = NULL;
330 	const char *ptr = NULL;
331 
332 	snprintf(buf, sizeof(buf), "%s/%ld/attr/%s", "/proc", (long int)pid,
333 		 val);
334 
335 	if (!(fp = fopen(buf, "rb")))
336 		return (-1);
337 
338 	ptr = fgets(buf, sizeof(buf), fp);
339 
340 	fclose(fp);
341 
342 	*con = NULL;
343 	if (ptr) {		/* return *con = NULL, when proc file is empty */
344 		char *tmp = strchr(ptr, '\n');
345 
346 		if (tmp)
347 			*tmp = 0;
348 
349 		if (*ptr && !(*con = strdup(ptr)))
350 			return (-1);
351 	}
352 
353 	return (0);
354 }
355 
356 static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
357 {
358 	return (my_getXcon_raw(pid, con, "exec"));
359 }
360 static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
361 {
362 	return (my_getXcon_raw(pid, con, "fscreate"));
363 }
364 static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
365 {
366 	return (my_getXcon_raw(pid, con, "keycreate"));
367 }
368 
369 static security_context_t get_scon(void)
370 {
371 	static char dummy_NIL[1] = "";
372 	security_context_t con = NULL;
373 	int ret = -1;
374 	int raw = TRUE;
375 
376 	switch (opts->from_type) {
377 	case OPTS_FROM_ARG:
378 		if (!(con = strdup(opts->f.arg)))
379 			err(EXIT_FAILURE,
380 			    " Couldn't allocate security context");
381 		raw = !opts->disp_raw;	/* always do conversion */
382 		break;
383 
384 	case OPTS_FROM_STDIN:
385 		{
386 			char buf[4096] = "";
387 			char *ptr = buf;
388 
389 			while (!*ptr) {
390 				if (!(ptr = fgets(buf, sizeof(buf), stdin)))
391 					err(EXIT_FAILURE,
392 					    " Couldn't read security context");
393 
394 				ptr += strspn(ptr, " \n\t");
395 				ptr[strcspn(ptr, " \n\t")] = 0;
396 			}
397 
398 			if (!(con = strdup(ptr)))
399 				err(EXIT_FAILURE,
400 				    " Couldn't allocate security context");
401 
402 			raw = !opts->disp_raw;	/* always do conversion */
403 			break;
404 		}
405 
406 	case OPTS_FROM_CUR:
407 		ret = getcon_raw(&con);
408 
409 		if (ret == -1)
410 			err(EXIT_FAILURE,
411 			    " Couldn't get current security context");
412 		break;
413 	case OPTS_FROM_CUREXE:
414 		ret = getexeccon_raw(&con);
415 
416 		if (ret == -1)
417 			err(EXIT_FAILURE,
418 			    " Couldn't get current exec security context");
419 
420 		if (!con)
421 			con = strdup(dummy_NIL);
422 		break;
423 	case OPTS_FROM_CURFS:
424 		ret = getfscreatecon_raw(&con);
425 
426 		if (ret == -1)
427 			err(EXIT_FAILURE,
428 			    " Couldn't get current fs security context");
429 
430 		if (!con)
431 			con = strdup(dummy_NIL);
432 		break;
433 	case OPTS_FROM_CURKEY:
434 		ret = getkeycreatecon_raw(&con);
435 
436 		if (ret == -1)
437 			err(EXIT_FAILURE,
438 			    " Couldn't get current key security context");
439 
440 		if (!con)
441 			con = strdup(dummy_NIL);
442 		break;
443 
444 	case OPTS_FROM_PROC:
445 		ret = getpidcon_raw(opts->f.pid, &con);
446 
447 		if (ret == -1)
448 			err(EXIT_FAILURE,
449 			    " Couldn't get security context for pid %lu",
450 			    (unsigned long)opts->f.pid);
451 		break;
452 	case OPTS_FROM_PROCEXE:
453 		ret = my_getpidexeccon_raw(opts->f.pid, &con);
454 
455 		if (ret == -1)
456 			err(EXIT_FAILURE,
457 			    " Couldn't get security context for pid %lu",
458 			    (unsigned long)opts->f.pid);
459 
460 		if (!con)
461 			con = strdup(dummy_NIL);
462 		break;
463 	case OPTS_FROM_PROCFS:
464 		ret = my_getpidfscreatecon_raw(opts->f.pid, &con);
465 
466 		if (ret == -1)
467 			err(EXIT_FAILURE,
468 			    " Couldn't get security context for pid %lu",
469 			    (unsigned long)opts->f.pid);
470 
471 		if (!con)
472 			con = strdup(dummy_NIL);
473 		/* disabled -- override with normal context ...
474 		   {
475 		   opts->from_type = OPTS_FROM_PROC;
476 		   return (get_scon());
477 		   } */
478 		break;
479 	case OPTS_FROM_PROCKEY:
480 		ret = my_getpidkeycreatecon_raw(opts->f.pid, &con);
481 
482 		if (ret == -1)
483 			err(EXIT_FAILURE,
484 			    " Couldn't get security context for pid %lu",
485 			    (unsigned long)opts->f.pid);
486 
487 		if (!con)
488 			con = strdup(dummy_NIL);
489 		break;
490 
491 	case OPTS_FROM_FILE:
492 		ret = getfilecon_raw(opts->f.file, &con);
493 
494 		if (ret == -1)
495 			err(EXIT_FAILURE,
496 			    " Couldn't get security context for file %s",
497 			    opts->f.file);
498 		break;
499 
500 	case OPTS_FROM_LINK:
501 		ret = lgetfilecon_raw(opts->f.link, &con);
502 
503 		if (ret == -1)
504 			err(EXIT_FAILURE,
505 			    " Couldn't get security context for symlink %s",
506 			    opts->f.link);
507 		break;
508 
509 	default:
510 		assert(FALSE);
511 	}
512 
513 	if (opts->disp_raw != raw) {
514 		security_context_t ncon = NULL;
515 
516 		if (opts->disp_raw)
517 			selinux_trans_to_raw_context(con, &ncon);
518 		else
519 			selinux_raw_to_trans_context(con, &ncon);
520 
521 		freecon(con);
522 		con = ncon;
523 	}
524 
525 	return (con);
526 }
527 
528 static void disp__con_val(const char *name, const char *val)
529 {
530 	static int done = FALSE;
531 
532 	assert(name);
533 
534 	if (!val)
535 		val = "";	/* targeted has no "level" etc.,
536 				   any errors should happen at context_new() time */
537 
538 	if (opts->disp_prompt) {
539 		if (xstreq("mls-range", name) && !*val)
540 			return;	/* skip, mls-range if it's empty */
541 
542 		fprintf(stdout, "%s%s", done ? ":" : "", val);
543 	} else if (disp_multi())
544 		fprintf(stdout, "%s: %s\n", name, val);
545 	else
546 		fprintf(stdout, "%s\n", val);
547 
548 	done = TRUE;
549 }
550 
551 static void disp_con(security_context_t scon)
552 {
553 	context_t con = NULL;
554 
555 	if (!*scon) {		/* --self-exec and --self-fs etc. */
556 		if (opts->disp_user)
557 			disp__con_val("user", NULL);
558 		if (opts->disp_role)
559 			disp__con_val("role", NULL);
560 		if (opts->disp_type)
561 			disp__con_val("type", NULL);
562 		if (opts->disp_sen)
563 			disp__con_val("sensitivity", NULL);
564 		if (opts->disp_clr)
565 			disp__con_val("clearance", NULL);
566 		if (opts->disp_mlsr)
567 			disp__con_val("mls-range", NULL);
568 		return;
569 	}
570 
571 	if (!(con = context_new(scon)))
572 		errx(EXIT_FAILURE, "Couldn't create context from: %s", scon);
573 
574 	if (opts->disp_user)
575 		disp__con_val("user", context_user_get(con));
576 	if (opts->disp_role)
577 		disp__con_val("role", context_role_get(con));
578 	if (opts->disp_type)
579 		disp__con_val("type", context_type_get(con));
580 	if (opts->disp_sen) {
581 		const char *val = NULL;
582 		char *tmp = NULL;
583 
584 		val = context_range_get(con);
585 		if (!val)
586 			val = "";	/* targeted has no "level" etc.,
587 					   any errors should happen at context_new() time */
588 
589 		tmp = strdup(val);
590 		if (!tmp)
591 			errx(EXIT_FAILURE, "Couldn't create context from: %s",
592 			     scon);
593 		if (strchr(tmp, '-'))
594 			*strchr(tmp, '-') = 0;
595 
596 		disp__con_val("sensitivity", tmp);
597 
598 		free(tmp);
599 	}
600 	if (opts->disp_clr) {
601 		const char *val = NULL;
602 		char *tmp = NULL;
603 
604 		val = context_range_get(con);
605 		if (!val)
606 			val = "";	/* targeted has no "level" etc.,
607 					   any errors should happen at context_new() time */
608 
609 		tmp = strdup(val);
610 		if (!tmp)
611 			errx(EXIT_FAILURE, "Couldn't create context from: %s",
612 			     scon);
613 		if (strchr(tmp, '-'))
614 			disp__con_val("clearance", strchr(tmp, '-') + 1);
615 		else
616 			disp__con_val("clearance", tmp);
617 
618 		free(tmp);
619 	}
620 
621 	if (opts->disp_mlsr)
622 		disp__con_val("mls-range", context_range_get(con));
623 
624 	context_free(con);
625 }
626 
627 int main(int argc, char *argv[])
628 {
629 	security_context_t scon = NULL;
630 
631 	cmd_line(argc, argv);
632 
633 	scon = get_scon();
634 
635 	disp_con(scon);
636 
637 	freecon(scon);
638 
639 	exit(EXIT_SUCCESS);
640 }

policycoreutils-2.1.13/semanage/default_encoding/default_encoding.c

Location Tool Test ID Issue
default_encoding.c:37:37 cpychecker mismatching-type-in-format-string setdefaultencoding Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s:setdefaultencoding"
default_encoding.c:44:1 cpychecker returns-NULL-without-setting-exception setdefaultencoding returning (PyObject*)NULL without setting an exception
 1 /*
 2  * Authors:
 3  *   John Dennis <jdennis@redhat.com>
 4  *
 5  * Copyright (C) 2009  Red Hat
 6  * see file 'COPYING' for use and warranty information
 7  *
 8  * This program is free software; you can redistribute it and/or
 9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include <Python.h>
23 
24 PyDoc_STRVAR(setdefaultencoding_doc,
25 "setdefaultencoding(encoding='utf-8')\n\
26 \n\
27 Set the current default string encoding used by the Unicode implementation.\n\
28 Defaults to utf-8."
29 );
30 
31 static PyObject *
32 setdefaultencoding(PyObject *self, PyObject *args, PyObject *kwds)
33 {
34     static char *kwlist[] = {"utf-8", NULL};
35     char *encoding;
36 
37     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:setdefaultencoding", kwlist, &encoding))
Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s:setdefaultencoding"
argument 5 ("&encoding") had type "char * *" but was expecting "const char * *" for format code "s"
(emitted by cpychecker)
38 return NULL; 39 40 if (PyUnicode_SetDefaultEncoding(encoding)) 41 return NULL; 42 43 Py_RETURN_NONE; 44 }
returning (PyObject*)NULL without setting an exception
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

45 46 static PyMethodDef methods[] = { 47 {"setdefaultencoding", (PyCFunction)setdefaultencoding, METH_VARARGS|METH_KEYWORDS, setdefaultencoding_doc}, 48 {NULL, NULL} /* sentinel */ 49 }; 50 51 52 PyMODINIT_FUNC 53 initdefault_encoding_utf8(void) 54 { 55 PyUnicode_SetDefaultEncoding("utf-8"); 56 Py_InitModule3("default_encoding_utf8", methods, "Forces the default encoding to utf-8"); 57 }

policycoreutils-2.1.13/semodule/semodule.c

No issues found

  1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
  2  *          Joshua Brindle <jbrindle@tresys.com>
  3  *          Jason Tang <jtang@tresys.com>
  4  *
  5  * Copyright (C) 2004-2005 Tresys Technology, LLC
  6  *      This program is free software; you can redistribute it and/or
  7  *      modify it under the terms of the GNU General Public License as
  8  *      published by the Free Software Foundation, version 2.
  9  */
 10 
 11 #include <fcntl.h>
 12 #include <getopt.h>
 13 #include <signal.h>
 14 #include <stdio.h>
 15 #include <stdlib.h>
 16 #include <errno.h>
 17 #include <string.h>
 18 #include <unistd.h>
 19 #include <sys/mman.h>
 20 #include <sys/stat.h>
 21 #include <sys/types.h>
 22 
 23 #include <semanage/modules.h>
 24 
 25 enum client_modes { NO_MODE, INSTALL_M, UPGRADE_M, BASE_M, ENABLE_M, DISABLE_M, REMOVE_M,
 26 	LIST_M, RELOAD
 27 };
 28 /* list of modes in which one ought to commit afterwards */
 29 static const int do_commit[] = {
 30 	0, 1, 1, 1, 1, 1, 1,
 31 	0, 0
 32 };
 33 
 34 struct command {
 35 	enum client_modes mode;
 36 	char *arg;
 37 };
 38 static struct command *commands = NULL;
 39 static int num_commands = 0;
 40 
 41 /* options given on command line */
 42 static int verbose;
 43 static int reload;
 44 static int no_reload;
 45 static int create_store;
 46 static int build;
 47 static int disable_dontaudit;
 48 static int preserve_tunables;
 49 
 50 static semanage_handle_t *sh = NULL;
 51 static char *store;
 52 
 53 extern char *optarg;
 54 extern int optind;
 55 
 56 static void cleanup(void)
 57 {
 58 	while (--num_commands >= 0) {
 59 		free(commands[num_commands].arg);
 60 	}
 61 	free(commands);
 62 }
 63 
 64 /* Signal handlers. */
 65 static void handle_signal(int sig_num)
 66 {
 67 	if (sig_num == SIGINT || sig_num == SIGQUIT || sig_num == SIGTERM) {
 68 		/* catch these signals, and then drop them */
 69 	}
 70 }
 71 
 72 static void set_store(char *storename)
 73 {
 74 	/* For now this only supports a store name, later on this 
 75 	 * should support an address for a remote connection */
 76 
 77 	if ((store = strdup(storename)) == NULL) {
 78 		fprintf(stderr, "Out of memory!\n");
 79 		goto bad;
 80 	}
 81 
 82 	return;
 83 
 84       bad:
 85 	cleanup();
 86 	exit(1);
 87 }
 88 
 89 /* Establish signal handlers for the process. */
 90 static void create_signal_handlers(void)
 91 {
 92 	if (signal(SIGINT, handle_signal) == SIG_ERR ||
 93 	    signal(SIGQUIT, handle_signal) == SIG_ERR ||
 94 	    signal(SIGTERM, handle_signal) == SIG_ERR) {
 95 		fprintf(stderr, "Could not set up signal handler.\n");
 96 		exit(255);
 97 	}
 98 }
 99 
100 static void usage(char *progname)
101 {
102 	printf("usage:  %s [options]... MODE [MODES]...\n", progname);
103 	printf("Manage SELinux policy modules.\n");
104 	printf("MODES:\n");
105 	printf("  -R, --reload		    reload policy\n");
106 	printf("  -B, --build		    build and reload policy\n");
107 	printf("  -i,--install=MODULE_PKG   install a new module\n");
108 	printf("  -u,--upgrade=MODULE_PKG   upgrade existing module\n");
109 	printf("  -b,--base=MODULE_PKG      install new base module\n");
110 	printf("  -e,--enable=MODULE_PKG    enable existing module\n");
111 	printf("  -d,--disable=MODULE_PKG   disable existing module\n");
112  	printf("  -r,--remove=MODULE_NAME   remove existing module\n");
113 	printf
114 	    ("  -l,--list-modules         display list of installed modules\n");
115 	printf("Other options:\n");
116 	printf("  -s,--store	   name of the store to operate on\n");
117 	printf("  -N,-n,--noreload do not reload policy after commit\n");
118 	printf("  -h,--help        print this message and quit\n");
119 	printf("  -v,--verbose     be verbose\n");
120 	printf("  -D,--disable_dontaudit	Remove dontaudits from policy\n");
121 	printf("  -P,--preserve_tunables	Preserve tunables in policy\n");
122 	printf("  -p,--path        use an alternate path for the policy root\n");
123 }
124 
125 /* Sets the global mode variable to new_mode, but only if no other
126  * mode has been given. */
127 static void set_mode(enum client_modes new_mode, char *arg)
128 {
129 	struct command *c;
130 	char *s;
131 	if ((c = realloc(commands, sizeof(*c) * (num_commands + 1))) == NULL) {
132 		fprintf(stderr, "Out of memory!\n");
133 		cleanup();
134 		exit(1);
135 	}
136 	commands = c;
137 	commands[num_commands].mode = new_mode;
138 	commands[num_commands].arg = NULL;
139 	num_commands++;
140 	if (arg != NULL) {
141 		if ((s = strdup(arg)) == NULL) {
142 			fprintf(stderr, "Out of memory!\n");
143 			cleanup();
144 			exit(1);
145 		}
146 		commands[num_commands - 1].arg = s;
147 	}
148 }
149 
150 /* Parse command line and set global options. */
151 static void parse_command_line(int argc, char **argv)
152 {
153 	static struct option opts[] = {
154 		{"store", required_argument, NULL, 's'},
155 		{"base", required_argument, NULL, 'b'},
156 		{"help", 0, NULL, 'h'},
157 		{"install", required_argument, NULL, 'i'},
158 		{"list-modules", 0, NULL, 'l'},
159 		{"verbose", 0, NULL, 'v'},
160 		{"enable", required_argument, NULL, 'e'},
161 		{"disable", required_argument, NULL, 'd'},
162 		{"remove", required_argument, NULL, 'r'},
163 		{"upgrade", required_argument, NULL, 'u'},
164 		{"reload", 0, NULL, 'R'},
165 		{"noreload", 0, NULL, 'n'},
166 		{"build", 0, NULL, 'B'},
167 		{"disable_dontaudit", 0, NULL, 'D'},
168 		{"preserve_tunables", 0, NULL, 'P'},
169 		{"path", required_argument, NULL, 'p'},
170 		{NULL, 0, NULL, 0}
171 	};
172 	int i;
173 	verbose = 0;
174 	reload = 0;
175 	no_reload = 0;
176 	create_store = 0;
177 	while ((i =
178 		getopt_long(argc, argv, "p:s:b:hi:lvqe:d:r:u:RnNBDP", opts,
179 			    NULL)) != -1) {
180 		switch (i) {
181 		case 'b':
182 			set_mode(BASE_M, optarg);
183 			create_store = 1;
184 			break;
185 		case 'h':
186 			usage(argv[0]);
187 			exit(0);
188 		case 'i':
189 			set_mode(INSTALL_M, optarg);
190 			break;
191 		case 'l':
192 			set_mode(LIST_M, NULL);
193 			break;
194 		case 'v':
195 			verbose = 1;
196 			break;
197 		case 'e':
198 			set_mode(ENABLE_M, optarg);
199 			break;
200 		case 'd':
201 			set_mode(DISABLE_M, optarg);
202 			break;
203 		case 'r':
204 			set_mode(REMOVE_M, optarg);
205 			break;
206 		case 'p':
207 			semanage_set_root(optarg);
208 			break;
209 		case 'u':
210 			set_mode(UPGRADE_M, optarg);
211 			break;
212 		case 's':
213 			set_store(optarg);
214 			break;
215 		case 'R':
216 			reload = 1;
217 			break;
218 		case 'n':
219 			no_reload = 1;
220 			break;
221 		case 'N':
222 			no_reload = 1;
223 			break;
224 		case 'B':
225 			build = 1;
226 			break;
227 		case 'D':
228 			disable_dontaudit = 1;
229 			break;
230 		case 'P':
231 			preserve_tunables = 1;
232 			break;
233 		case '?':
234 		default:{
235 				usage(argv[0]);
236 				exit(1);
237 			}
238 		}
239 	}
240 	if ((build || reload) && num_commands) {
241 		fprintf(stderr,
242 			"build or reload should not be used with other commands\n");
243 		usage(argv[0]);
244 		exit(1);
245 	}
246 	if (num_commands == 0 && reload == 0 && build == 0) {
247 		fprintf(stderr, "At least one mode must be specified.\n");
248 		usage(argv[0]);
249 		exit(1);
250 	}
251 
252 	if (optind < argc) {
253 		int mode;
254 		/* if -i/u/r was the last command treat any remaining
255 		 * arguments as args. Will allow 'semodule -i *.pp' to
256 		 * work as expected.
257 		 */
258 
259 		if (commands && commands[num_commands - 1].mode == INSTALL_M) {
260 			mode = INSTALL_M;
261 		} else if (commands && commands[num_commands - 1].mode == UPGRADE_M) {
262 			mode = UPGRADE_M;
263 		} else if (commands && commands[num_commands - 1].mode == REMOVE_M) {
264 			mode = REMOVE_M;
265 		} else if (commands && commands[num_commands - 1].mode == ENABLE_M) {
266 			mode = ENABLE_M;
267 		} else if (commands && commands[num_commands - 1].mode == DISABLE_M) {
268 			mode = DISABLE_M;
269 		} else {
270 			fprintf(stderr, "unknown additional arguments:\n");
271 			while (optind < argc)
272 				fprintf(stderr, " %s", argv[optind++]);
273 			fprintf(stderr, "\n\n");
274 			usage(argv[0]);
275 			exit(1);
276 		}
277 		while (optind < argc)
278 			set_mode(mode, argv[optind++]);
279 	}
280 }
281 
282 int main(int argc, char *argv[])
283 {
284 	int i, commit = 0;
285 	int result;
286 	int status = EXIT_FAILURE;
287 
288 	create_signal_handlers();
289 	parse_command_line(argc, argv);
290 
291 	if (build)
292 		commit = 1;
293 
294 	sh = semanage_handle_create();
295 	if (!sh) {
296 		fprintf(stderr, "%s:  Could not create semanage handle\n",
297 			argv[0]);
298 		goto cleanup_nohandle;
299 	}
300 
301 	if (store) {
302 		/* Set the store we want to connect to, before connecting.
303 		 * this will always set a direct connection now, an additional
304 		 * option will need to be used later to specify a policy server 
305 		 * location */
306 		semanage_select_store(sh, store, SEMANAGE_CON_DIRECT);
307 	}
308 
309 	/* if installing base module create store if necessary, for bootstrapping */
310 	semanage_set_create_store(sh, create_store);
311 
312 	if (!create_store) {
313 		if (!semanage_is_managed(sh)) {
314 			fprintf(stderr,
315 				"%s: SELinux policy is not managed or store cannot be accessed.\n",
316 				argv[0]);
317 			goto cleanup;
318 		}
319 
320 		if (semanage_access_check(sh) < SEMANAGE_CAN_READ) {
321 			fprintf(stderr, "%s: Cannot read policy store.\n",
322 				argv[0]);
323 			goto cleanup;
324 		}
325 	}
326 
327 	if ((result = semanage_connect(sh)) < 0) {
328 		fprintf(stderr, "%s:  Could not connect to policy handler\n",
329 			argv[0]);
330 		goto cleanup;
331 	}
332 
333 	if (reload) {
334 		if ((result = semanage_reload_policy(sh)) < 0) {
335 			fprintf(stderr, "%s:  Could not reload policy\n",
336 				argv[0]);
337 			goto cleanup;
338 		}
339 	}
340 
341 	if (build) {
342 		if ((result = semanage_begin_transaction(sh)) < 0) {
343 			fprintf(stderr, "%s:  Could not begin transaction:  %s\n",
344 				argv[0], errno ? strerror(errno) : "");
345 			goto cleanup;
346 		}
347 	}
348 
349 	for (i = 0; i < num_commands; i++) {
350 		enum client_modes mode = commands[i].mode;
351 		char *mode_arg = commands[i].arg;
352 		switch (mode) {
353 		case INSTALL_M:{
354 				if (verbose) {
355 					printf
356 					    ("Attempting to install module '%s':\n",
357 					     mode_arg);
358 				}
359 				result =
360 				    semanage_module_install_file(sh, mode_arg);
361 				break;
362 			}
363 		case UPGRADE_M:{
364 				if (verbose) {
365 					printf
366 					    ("Attempting to upgrade module '%s':\n",
367 					     mode_arg);
368 				}
369 				result =
370 				    semanage_module_upgrade_file(sh, mode_arg);
371 				break;
372 			}
373 		case BASE_M:{
374 				if (verbose) {
375 					printf
376 					    ("Attempting to install base module '%s':\n",
377 					     mode_arg);
378 				}
379 				result =
380 				    semanage_module_install_base_file(sh, mode_arg);
381 				break;
382 			}
383 		case ENABLE_M:{
384 				if (verbose) {
385 					printf
386 					    ("Attempting to enable module '%s':\n",
387 					     mode_arg);
388 				}
389 				result = semanage_module_enable(sh, mode_arg);
390 				if ( result == -2 ) { 
391 					continue;
392 				}
393 				break;
394 			}
395 		case DISABLE_M:{
396 				if (verbose) {
397 					printf
398 					    ("Attempting to disable module '%s':\n",
399 					     mode_arg);
400 				}
401 				result = semanage_module_disable(sh, mode_arg);
402 				if ( result == -2 ) { 
403 					continue;
404 				}
405 				break;
406 			}
407 		case REMOVE_M:{
408 				if (verbose) {
409 					printf
410 					    ("Attempting to remove module '%s':\n",
411 					     mode_arg);
412 				}
413 				result = semanage_module_remove(sh, mode_arg);
414 				if ( result == -2 ) { 
415 					continue;
416 				}
417 				break;
418 			}
419 		case LIST_M:{
420 				semanage_module_info_t *modinfo;
421 				int num_modules;
422 				if (verbose) {
423 					printf
424 					    ("Attempting to list active modules:\n");
425 				}
426 				if ((result =
427 				     semanage_module_list(sh, &modinfo,
428 							  &num_modules)) >= 0) {
429 					int j;
430 					if (num_modules == 0) {
431 						printf("No modules.\n");
432 					}
433 					for (j = 0; j < num_modules; j++) {
434 						semanage_module_info_t *m =
435 						    semanage_module_list_nth
436 						    (modinfo, j);
437 						printf("%s\t%s\t%s\n",
438 						       semanage_module_get_name
439 						       (m),
440 						       semanage_module_get_version
441 						       (m), 
442 						       (semanage_module_get_enabled(m) ? "" : "Disabled"));
443 						semanage_module_info_datum_destroy
444 						    (m);
445 					}
446 					free(modinfo);
447 				}
448 				break;
449 			}
450 		default:{
451 				fprintf(stderr,
452 					"%s:  Unknown mode specified.\n",
453 					argv[0]);
454 				usage(argv[0]);
455 				goto cleanup;
456 			}
457 		}
458 		commit += do_commit[mode];
459 		if (result < 0) {
460 			fprintf(stderr, "%s:  Failed on %s!\n", argv[0],
461 				mode_arg ? : "list");
462 			goto cleanup;
463 		} else if (verbose) {
464 			printf("Ok: return value of %d.\n", result);
465 		}
466 	}
467 
468 	if (commit) {
469 		if (verbose)
470 			printf("Committing changes:\n");
471 		if (no_reload)
472 			semanage_set_reload(sh, 0);
473 		if (build)
474 			semanage_set_rebuild(sh, 1);
475 		if (disable_dontaudit)
476 			semanage_set_disable_dontaudit(sh, 1);
477 		else if (build)
478 			semanage_set_disable_dontaudit(sh, 0);
479 		if (preserve_tunables)
480 			semanage_set_preserve_tunables(sh, 1);
481 
482 		result = semanage_commit(sh);
483 	}
484 
485 	if (result < 0) {
486 		fprintf(stderr, "%s:  Failed!\n", argv[0]);
487 		goto cleanup;
488 	} else if (commit && verbose) {
489 		printf("Ok: transaction number %d.\n", result);
490 	}
491 
492 	if (semanage_disconnect(sh) < 0) {
493 		fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
494 		goto cleanup;
495 	}
496 	status = EXIT_SUCCESS;
497 
498       cleanup:
499 	if (semanage_is_connected(sh)) {
500 		if (semanage_disconnect(sh) < 0) {
501 			fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
502 		}
503 	}
504 	semanage_handle_destroy(sh);
505 
506       cleanup_nohandle:
507 	cleanup();
508 	exit(status);
509 }

policycoreutils-2.1.13/semodule_deps/semodule_deps.c

No issues found

  1 /* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
  2  *
  3  * Copyright (C) 2006 Tresys Technology, LLC
  4  * Copyright (C) 2006-2007 Red Hat, Inc.
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation, version 2.
  9  *
 10  */
 11 
 12 /* Because we _must_ muck around in the internal representation of
 13  * the policydb (and include the internal header below) this program
 14  * must be statically linked to libsepol like checkpolicy. It is
 15  * not clear if it is worthwhile to fix this, as exposing the details
 16  * of avrule_blocks - even in an ABI safe way - seems undesirable.
 17  */
 18 #include <sepol/module.h>
 19 #include <sepol/errcodes.h>
 20 #include <sepol/policydb/policydb.h>
 21 
 22 #include <getopt.h>
 23 #include <fcntl.h>
 24 #include <stdio.h>
 25 #include <errno.h>
 26 #include <sys/mman.h>
 27 #include <sys/types.h>
 28 #include <sys/stat.h>
 29 #include <stdlib.h>
 30 #include <unistd.h>
 31 #include <string.h>
 32 #include <assert.h>
 33 
 34 /* for getopt */
 35 extern char *optarg;
 36 extern int optind;
 37 
 38 /* This is really a horrible hack, but the base module
 39  * is referred to with the following name. The same
 40  * thing is done in the linker for displaying error
 41  * messages.
 42  */
 43 #define BASE_NAME "BASE"
 44 
 45 static void usage(char *program_name)
 46 {
 47 	printf("usage: %s [-v -g -b] basemodpkg modpkg1 [modpkg2 ... ]\n",
 48 	       program_name);
 49 	exit(1);
 50 }
 51 
 52 /* Basic string hash and compare for the hashtables used in
 53  * generate_requires. Copied from symtab.c.
 54  */
 55 static unsigned int reqsymhash(hashtab_t h, hashtab_key_t key)
 56 {
 57 	char *p, *keyp;
 58 	size_t size;
 59 	unsigned int val;
 60 
 61 	val = 0;
 62 	keyp = (char *)key;
 63 	size = strlen(keyp);
 64 	for (p = keyp; ((size_t) (p - keyp)) < size; p++)
 65 		val =
 66 		    (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
 67 	return val & (h->size - 1);
 68 }
 69 
 70 static int reqsymcmp(hashtab_t h
 71 		     __attribute__ ((unused)), hashtab_key_t key1,
 72 		     hashtab_key_t key2)
 73 {
 74 	char *keyp1, *keyp2;
 75 
 76 	keyp1 = (char *)key1;
 77 	keyp2 = (char *)key2;
 78 	return strcmp(keyp1, keyp2);
 79 }
 80 
 81 /* Load a policy package from the given filename. Progname is used for
 82  * error reporting.
 83  */
 84 static sepol_module_package_t *load_module(char *filename, char *progname)
 85 {
 86 	int ret;
 87 	FILE *fp = NULL;
 88 	struct sepol_policy_file *pf = NULL;
 89 	sepol_module_package_t *p = NULL;
 90 
 91 	if (sepol_module_package_create(&p)) {
 92 		fprintf(stderr, "%s:  Out of memory\n", progname);
 93 		goto bad;
 94 	}
 95 	if (sepol_policy_file_create(&pf)) {
 96 		fprintf(stderr, "%s:  Out of memory\n", progname);
 97 		goto bad;
 98 	}
 99 	fp = fopen(filename, "r");
100 	if (!fp) {
101 		fprintf(stderr, "%s:  Could not open package %s:  %s", progname,
102 			filename, strerror(errno));
103 		goto bad;
104 	}
105 	sepol_policy_file_set_fp(pf, fp);
106 
107 	ret = sepol_module_package_read(p, pf, 0);
108 	if (ret) {
109 		fprintf(stderr, "%s:  Error while reading package from %s\n",
110 			progname, filename);
111 		goto bad;
112 	}
113 	fclose(fp);
114 	sepol_policy_file_free(pf);
115 	return p;
116       bad:
117 	sepol_module_package_free(p);
118 	sepol_policy_file_free(pf);
119 	if (fp)
120 		fclose(fp);
121 	return NULL;
122 }
123 
124 /* This function generates the requirements graph and stores it in
125  * a set of nested hashtables. The top level hash table stores modules
126  * keyed by name. The value of that module is a hashtable storing all
127  * of the requirements keyed by name. There is no value for the requirements
128  * hashtable.
129  *
130  * This only tracks symbols that are _required_ - optional symbols
131  * are completely ignored. A future version might look at this.
132  *
133  * This requirement generation only looks at booleans and types because:
134  *  - object classes: (for now) only present in bases
135  *  - roles: since they are multiply declared it is not clear how
136  *           to present these requirements as they will be satisfied
137  *           by multiple modules.
138  *  - users: same problem as roles plus they are usually defined outside
139  *           of the policy.
140  *  - levels / cats: can't be required or used in modules.
141  */
142 static hashtab_t generate_requires(policydb_t * p)
143 {
144 	avrule_block_t *block;
145 	avrule_decl_t *decl;
146 	char *mod_name, *req_name, *id;
147 	ebitmap_t *b;
148 	ebitmap_node_t *node;
149 	uint32_t i, j;
150 	int ret;
151 	scope_datum_t *scope;
152 	hashtab_t mods;
153 	hashtab_t reqs;
154 
155 	mods = hashtab_create(reqsymhash, reqsymcmp, 64);
156 	if (mods == NULL)
157 		return NULL;
158 
159 	for (block = p->global; block != NULL; block = block->next) {
160 		if (block->flags & AVRULE_OPTIONAL)
161 			continue;
162 		for (decl = block->branch_list; decl != NULL; decl = decl->next) {
163 			mod_name =
164 			    decl->module_name ? decl->module_name : BASE_NAME;
165 			for (i = 0; i < SYM_NUM; i++) {
166 				if (!(i == SYM_TYPES || i == SYM_BOOLS))
167 					continue;
168 				b = &decl->required.scope[i];
169 				ebitmap_for_each_bit(b, node, j) {
170 					if (!ebitmap_node_get_bit(node, j))
171 						continue;
172 					id = p->sym_val_to_name[i][j];
173 					scope =
174 					    (scope_datum_t *) hashtab_search(p->
175 									     scope
176 									     [i].
177 									     table,
178 									     id);
179 					/* since this is only called after a successful link,
180 					 * this should never happen */
181 					assert(scope->scope == SCOPE_DECL);
182 					req_name =
183 					    p->decl_val_to_struct[scope->
184 								  decl_ids[0]]->
185 					    module_name ? p->
186 					    decl_val_to_struct[scope->
187 							       decl_ids[0]]->
188 					    module_name : BASE_NAME;
189 
190 					reqs =
191 					    (hashtab_t) hashtab_search(mods,
192 								       mod_name);
193 					if (!reqs) {
194 						reqs =
195 						    hashtab_create(reqsymhash,
196 								   reqsymcmp,
197 								   64);
198 						if (reqs == NULL) {
199 							return NULL;
200 						}
201 						ret =
202 						    hashtab_insert(mods,
203 								   mod_name,
204 								   reqs);
205 						if (ret != SEPOL_OK)
206 							return NULL;
207 					}
208 					ret =
209 					    hashtab_insert(reqs, req_name,
210 							   NULL);
211 					if (!
212 					    (ret == SEPOL_EEXIST
213 					     || ret == SEPOL_OK))
214 						return NULL;
215 				}
216 			}
217 
218 		}
219 	}
220 
221 	return mods;
222 }
223 
224 static void free_requires(hashtab_t req)
225 {
226 	unsigned int i;
227 	hashtab_ptr_t cur;
228 
229 	/* We steal memory for everything stored in the hash tables
230 	 * from the policydb, so this only looks like it leaks.
231 	 */
232 	for (i = 0; i < req->size; i++) {
233 		cur = req->htable[i];
234 		while (cur != NULL) {
235 			hashtab_destroy((hashtab_t) cur->datum);
236 			cur = cur->next;
237 		}
238 	}
239 	hashtab_destroy(req);
240 }
241 
242 static void output_graphviz(hashtab_t mods, int exclude_base, FILE * f)
243 {
244 	unsigned int i, j;
245 	hashtab_ptr_t cur, cur2;
246 	hashtab_t reqs;
247 
248 	fprintf(f, "digraph mod_deps {\n");
249 	fprintf(f, "\toverlap=false\n");
250 
251 	for (i = 0; i < mods->size; i++) {
252 		cur = mods->htable[i];
253 		while (cur != NULL) {
254 			reqs = (hashtab_t) cur->datum;
255 			assert(reqs);
256 			for (j = 0; j < reqs->size; j++) {
257 				cur2 = reqs->htable[j];
258 				while (cur2 != NULL) {
259 					if (exclude_base
260 					    && strcmp(cur2->key,
261 						      BASE_NAME) == 0) {
262 						cur2 = cur2->next;
263 						continue;
264 					}
265 					fprintf(f, "\t%s -> %s\n", cur->key,
266 						cur2->key);
267 					cur2 = cur2->next;
268 				}
269 			}
270 			cur = cur->next;
271 		}
272 	}
273 	fprintf(f, "}\n");
274 }
275 
276 static void output_requirements(hashtab_t mods, int exclude_base, FILE * f)
277 {
278 	unsigned int i, j;
279 	hashtab_ptr_t cur, cur2;
280 	hashtab_t reqs;
281 	int found_req;
282 
283 	for (i = 0; i < mods->size; i++) {
284 		cur = mods->htable[i];
285 		while (cur != NULL) {
286 			reqs = (hashtab_t) cur->datum;
287 			assert(reqs);
288 			fprintf(f, "module: %s\n", cur->key);
289 			found_req = 0;
290 			for (j = 0; j < reqs->size; j++) {
291 				cur2 = reqs->htable[j];
292 				while (cur2 != NULL) {
293 					if (exclude_base
294 					    && strcmp(cur2->key,
295 						      BASE_NAME) == 0) {
296 						cur2 = cur2->next;
297 						continue;
298 					}
299 					found_req = 1;
300 					fprintf(f, "\t%s\n", cur2->key);
301 					cur2 = cur2->next;
302 				}
303 			}
304 			if (!found_req)
305 				fprintf(f, "\t[no dependencies]\n");
306 			cur = cur->next;
307 		}
308 	}
309 	fprintf(f, "}\n");
310 }
311 
312 /* Possible commands - see the command variable in
313  * main below and the man page for more info.
314  */
315 #define SHOW_DEPS    1
316 #define GEN_GRAPHVIZ 2
317 
318 int main(int argc, char **argv)
319 {
320 	int ch, i, num_mods;
321 	int verbose = 0, exclude_base = 1, command = SHOW_DEPS;
322 	char *basename;
323 	sepol_module_package_t *base, **mods;
324 	policydb_t *p;
325 	hashtab_t req;
326 
327 	while ((ch = getopt(argc, argv, "vgb")) != EOF) {
328 		switch (ch) {
329 		case 'v':
330 			verbose = 1;
331 			break;
332 		case 'g':
333 			command = GEN_GRAPHVIZ;
334 			break;
335 		case 'b':
336 			exclude_base = 0;
337 			break;
338 		default:
339 			usage(argv[0]);
340 		}
341 	}
342 
343 	/* check args */
344 	if (argc < 3 || !(optind != (argc - 1))) {
345 		fprintf(stderr,
346 			"%s:  You must provide the base module package and at least one other module package\n",
347 			argv[0]);
348 		usage(argv[0]);
349 	}
350 
351 	basename = argv[optind++];
352 	base = load_module(basename, argv[0]);
353 	if (!base) {
354 		fprintf(stderr,
355 			"%s:  Could not load base module from file %s\n",
356 			argv[0], basename);
357 		exit(1);
358 	}
359 
360 	num_mods = argc - optind;
361 	mods =
362 	    (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
363 					       * num_mods);
364 	if (!mods) {
365 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
366 		exit(1);
367 	}
368 	memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
369 
370 	for (i = 0; optind < argc; optind++, i++) {
371 		mods[i] = load_module(argv[optind], argv[0]);
372 		if (!mods[i]) {
373 			fprintf(stderr,
374 				"%s:  Could not load module from file %s\n",
375 				argv[0], argv[optind]);
376 			exit(1);
377 		}
378 	}
379 
380 	if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
381 		fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
382 		exit(1);
383 	}
384 
385 	p = (policydb_t *) sepol_module_package_get_policy(base);
386 	if (p == NULL)
387 		exit(1);
388 
389 	req = generate_requires(p);
390 	if (req == NULL)
391 		exit(1);
392 
393 	if (command == SHOW_DEPS)
394 		output_requirements(req, exclude_base, stdout);
395 	else
396 		output_graphviz(req, exclude_base, stdout);
397 
398 	sepol_module_package_free(base);
399 	for (i = 0; i < num_mods; i++)
400 		sepol_module_package_free(mods[i]);
401 
402 	free_requires(req);
403 
404 	exit(0);
405 }

policycoreutils-2.1.13/semodule_expand/semodule_expand.c

No issues found

  1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
  2  * 	    Joshua Brindle <jbrindle@tresys.com>
  3  *
  4  * Copyright (C) 2004 Tresys Technology, LLC
  5  *	This program is free software; you can redistribute it and/or modify
  6  *  	it under the terms of the GNU General Public License as published by
  7  *	the Free Software Foundation, version 2.
  8  */
  9 
 10 #include <sepol/policydb.h>
 11 #include <sepol/module.h>
 12 
 13 #include <getopt.h>
 14 #include <fcntl.h>
 15 #include <stdio.h>
 16 #include <errno.h>
 17 #include <sys/mman.h>
 18 #include <sys/types.h>
 19 #include <sys/stat.h>
 20 #include <stdlib.h>
 21 #include <unistd.h>
 22 #include <string.h>
 23 
 24 extern char *optarg;
 25 extern int optind;
 26 
 27 int policyvers = 0;
 28 
 29 #define EXPANDPOLICY_VERSION "1.0"
 30 
 31 static void usage(char *program_name)
 32 {
 33 	printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
 34 	       program_name);
 35 	exit(1);
 36 }
 37 
 38 int main(int argc, char **argv)
 39 {
 40 	char *basename, *outname;
 41 	int ch, ret, show_version = 0, verbose = 0;
 42 	struct sepol_policy_file *pf;
 43 	sepol_module_package_t *base;
 44 	sepol_policydb_t *out, *p;
 45 	FILE *fp, *outfile;
 46 	int check_assertions = 1;
 47 	sepol_handle_t *handle;
 48 
 49 	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
 50 		switch (ch) {
 51 		case 'V':
 52 			show_version = 1;
 53 			break;
 54 		case 'v':
 55 			verbose = 1;
 56 			break;
 57 		case 'c':{
 58 				long int n = strtol(optarg, NULL, 10);
 59 				if (errno) {
 60 					fprintf(stderr,
 61 						"%s:  Invalid policyvers specified: %s\n",
 62 						argv[0], optarg);
 63 					usage(argv[0]);
 64 					exit(1);
 65 				}
 66 				if (n < sepol_policy_kern_vers_min()
 67 				    || n > sepol_policy_kern_vers_max()) {
 68 					fprintf(stderr,
 69 						"%s:  policyvers value %ld not in range %d-%d\n",
 70 						argv[0], n,
 71 						sepol_policy_kern_vers_min(),
 72 						sepol_policy_kern_vers_max());
 73 					usage(argv[0]);
 74 					exit(1);
 75 				}
 76 				policyvers = n;
 77 				break;
 78 			}
 79 		case 'a':{
 80 				check_assertions = 0;
 81 				break;
 82 			}
 83 		default:
 84 			usage(argv[0]);
 85 		}
 86 	}
 87 
 88 	if (verbose) {
 89 		if (policyvers)
 90 			printf("Building version %d policy\n", policyvers);
 91 	}
 92 
 93 	if (show_version) {
 94 		printf("%s\n", EXPANDPOLICY_VERSION);
 95 		exit(0);
 96 	}
 97 
 98 	/* check args */
 99 	if (argc < 3 || !(optind != (argc - 1))) {
100 		fprintf(stderr,
101 			"%s:  You must provide the base module package and output filename\n",
102 			argv[0]);
103 		usage(argv[0]);
104 	}
105 
106 	basename = argv[optind++];
107 	outname = argv[optind];
108 
109 	handle = sepol_handle_create();
110 	if (!handle)
111 		exit(1);
112 
113 	if (sepol_policy_file_create(&pf)) {
114 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
115 		exit(1);
116 	}
117 
118 	/* read the base module */
119 	if (sepol_module_package_create(&base)) {
120 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
121 		exit(1);
122 	}
123 	fp = fopen(basename, "r");
124 	if (!fp) {
125 		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
126 			argv[0], basename, strerror(errno));
127 		exit(1);
128 	}
129 	sepol_policy_file_set_fp(pf, fp);
130 	ret = sepol_module_package_read(base, pf, 0);
131 	if (ret) {
132 		fprintf(stderr, "%s:  Error in reading package from %s\n",
133 			argv[0], basename);
134 		exit(1);
135 	}
136 	fclose(fp);
137 
138 	/* linking the base takes care of enabling optional avrules */
139 	p = sepol_module_package_get_policy(base);
140 	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
141 		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
142 		exit(1);
143 	}
144 
145 	/* create the output policy */
146 
147 	if (sepol_policydb_create(&out)) {
148 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
149 		exit(1);
150 	}
151 
152 	sepol_set_expand_consume_base(handle, 1);
153 
154 	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
155 		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
156 		exit(1);
157 	}
158 
159 	if (policyvers) {
160 		if (sepol_policydb_set_vers(out, policyvers)) {
161 			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
162 				policyvers);
163 			exit(1);
164 		}
165 	}
166 
167 	sepol_module_package_free(base);
168 
169 	outfile = fopen(outname, "w");
170 	if (!outfile) {
171 		perror(outname);
172 		exit(1);
173 	}
174 
175 	sepol_policy_file_set_fp(pf, outfile);
176 	ret = sepol_policydb_write(out, pf);
177 	if (ret) {
178 		fprintf(stderr,
179 			"%s:  Error while writing expanded policy to %s\n",
180 			argv[0], outname);
181 		exit(1);
182 	}
183 	fclose(outfile);
184 	sepol_handle_destroy(handle);
185 	sepol_policydb_free(out);
186 	sepol_policy_file_free(pf);
187 
188 	return 0;
189 }

policycoreutils-2.1.13/semodule_link/semodule_link.c

No issues found

  1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
  2  *
  3  * Copyright (C) 2004 Tresys Technology, LLC
  4  *	This program is free software; you can redistribute it and/or modify
  5  *  	it under the terms of the GNU General Public License as published by
  6  *	the Free Software Foundation, version 2.
  7  */
  8 
  9 #include <sepol/module.h>
 10 
 11 #include <getopt.h>
 12 #include <fcntl.h>
 13 #include <stdio.h>
 14 #include <errno.h>
 15 #include <sys/mman.h>
 16 #include <sys/types.h>
 17 #include <sys/stat.h>
 18 #include <stdlib.h>
 19 #include <unistd.h>
 20 #include <string.h>
 21 
 22 #define LINKPOLICY_VERSION "1.0"
 23 
 24 char *progname;
 25 extern char *optarg;
 26 extern int optind;
 27 
 28 static void usage(char *program_name)
 29 {
 30 	printf("usage: %s [-Vv] [-o outfile] basemodpkg modpkg1 [modpkg2]...\n",
 31 	       program_name);
 32 	exit(1);
 33 }
 34 
 35 static sepol_module_package_t *load_module(char *filename)
 36 {
 37 	int ret;
 38 	FILE *fp = NULL;
 39 	struct sepol_policy_file *pf = NULL;
 40 	sepol_module_package_t *p = NULL;
 41 
 42 	if (sepol_module_package_create(&p)) {
 43 		fprintf(stderr, "%s:  Out of memory\n", progname);
 44 		goto bad;
 45 	}
 46 	if (sepol_policy_file_create(&pf)) {
 47 		fprintf(stderr, "%s:  Out of memory\n", progname);
 48 		goto bad;
 49 	}
 50 	fp = fopen(filename, "r");
 51 	if (!fp) {
 52 		fprintf(stderr, "%s:  Could not open package %s:  %s", progname,
 53 			filename, strerror(errno));
 54 		goto bad;
 55 	}
 56 	sepol_policy_file_set_fp(pf, fp);
 57 
 58 	printf("%s:  loading package from file %s\n", progname, filename);
 59 
 60 	ret = sepol_module_package_read(p, pf, 0);
 61 	if (ret) {
 62 		fprintf(stderr, "%s:  Error while reading package from %s\n",
 63 			progname, filename);
 64 		goto bad;
 65 	}
 66 	fclose(fp);
 67 	sepol_policy_file_free(pf);
 68 	return p;
 69       bad:
 70 	sepol_module_package_free(p);
 71 	sepol_policy_file_free(pf);
 72 	if (fp)
 73 		fclose(fp);
 74 	return NULL;
 75 }
 76 
 77 int main(int argc, char **argv)
 78 {
 79 	int ch, i, show_version = 0, verbose = 0, num_mods;
 80 	char *basename, *outname = NULL;
 81 	sepol_module_package_t *base, **mods;
 82 	FILE *outfile;
 83 	struct sepol_policy_file *pf;
 84 
 85 	progname = argv[0];
 86 
 87 	while ((ch = getopt(argc, argv, "o:Vv")) != EOF) {
 88 		switch (ch) {
 89 		case 'V':
 90 			show_version = 1;
 91 			break;
 92 		case 'v':
 93 			verbose = 1;
 94 			break;
 95 		case 'o':
 96 			outname = optarg;
 97 			break;
 98 		default:
 99 			usage(argv[0]);
100 		}
101 	}
102 
103 	if (show_version) {
104 		printf("%s\n", LINKPOLICY_VERSION);
105 		exit(0);
106 	}
107 
108 	/* check args */
109 	if (argc < 3 || !(optind != (argc - 1))) {
110 		fprintf(stderr,
111 			"%s:  You must provide the base module package and at least one other module package\n",
112 			argv[0]);
113 		usage(argv[0]);
114 	}
115 
116 	basename = argv[optind++];
117 	base = load_module(basename);
118 	if (!base) {
119 		fprintf(stderr,
120 			"%s:  Could not load base module from file %s\n",
121 			argv[0], basename);
122 		exit(1);
123 	}
124 
125 	num_mods = argc - optind;
126 	mods =
127 	    (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
128 					       * num_mods);
129 	if (!mods) {
130 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
131 		exit(1);
132 	}
133 	memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
134 
135 	for (i = 0; optind < argc; optind++, i++) {
136 		mods[i] = load_module(argv[optind]);
137 		if (!mods[i]) {
138 			fprintf(stderr,
139 				"%s:  Could not load module from file %s\n",
140 				argv[0], argv[optind]);
141 			exit(1);
142 		}
143 	}
144 
145 	if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
146 		fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
147 		exit(1);
148 	}
149 
150 	if (outname) {
151 		outfile = fopen(outname, "w");
152 		if (!outfile) {
153 			perror(outname);
154 			exit(1);
155 		}
156 
157 		if (sepol_policy_file_create(&pf)) {
158 			fprintf(stderr, "%s:  Out of memory\n", argv[0]);
159 			exit(1);
160 		}
161 		sepol_policy_file_set_fp(pf, outfile);
162 		if (sepol_module_package_write(base, pf)) {
163 			fprintf(stderr, "%s:  Error writing linked package.\n",
164 				argv[0]);
165 			exit(1);
166 		}
167 		sepol_policy_file_free(pf);
168 		fclose(outfile);
169 	}
170 
171 	sepol_module_package_free(base);
172 	for (i = 0; i < num_mods; i++)
173 		sepol_module_package_free(mods[i]);
174 	free(mods);
175 	exit(0);
176 }

policycoreutils-2.1.13/semodule_package/semodule_package.c

No issues found

  1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
  2  *
  3  * Copyright (C) 2004 Tresys Technology, LLC
  4  *	This program is free software; you can redistribute it and/or modify
  5  *  	it under the terms of the GNU General Public License as published by
  6  *	the Free Software Foundation, version 2.
  7  */
  8 
  9 #include <sepol/module.h>
 10 #include <getopt.h>
 11 #include <fcntl.h>
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15 #include <unistd.h>
 16 #include <sys/types.h>
 17 #include <sys/stat.h>
 18 #include <sys/mman.h>
 19 #include <fcntl.h>
 20 #include <errno.h>
 21 
 22 char *progname = NULL;
 23 extern char *optarg;
 24 
 25 static void usage(char *prog)
 26 {
 27 	printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n",
 28 	       prog);
 29 	printf("Options:\n");
 30 	printf("  -o --outfile		Output file (required)\n");
 31 	printf("  -m --module		Module file (required)\n");
 32 	printf("  -f --fc		File contexts file\n");
 33 	printf("  -s --seuser		Seusers file (only valid in base)\n");
 34 	printf
 35 	    ("  -u --user_extra	user_extra file (only valid in base)\n");
 36 	printf("  -n --nc		Netfilter contexts file\n");
 37 	exit(1);
 38 }
 39 
 40 static int file_to_policy_file(char *filename, struct sepol_policy_file **pf,
 41 			       char *mode)
 42 {
 43 	FILE *f;
 44 
 45 	if (sepol_policy_file_create(pf)) {
 46 		fprintf(stderr, "%s:  Out of memory\n", progname);
 47 		return -1;
 48 	}
 49 
 50 	f = fopen(filename, mode);
 51 	if (!f) {
 52 		fprintf(stderr, "%s:  Could not open file %s:  %s\n", progname,
 53 			strerror(errno), filename);
 54 		return -1;
 55 	}
 56 	sepol_policy_file_set_fp(*pf, f);
 57 	return 0;
 58 }
 59 
 60 static int file_to_data(const char *path, char **data, size_t * len)
 61 {
 62 	int fd;
 63 	struct stat sb;
 64 	fd = open(path, O_RDONLY);
 65 	if (fd < 0) {
 66 		fprintf(stderr, "%s:  Failed to open %s:  %s\n", progname, path,
 67 			strerror(errno));
 68 		return -1;
 69 	}
 70 	if (fstat(fd, &sb) < 0) {
 71 		fprintf(stderr, "%s:  Failed to fstat %s:  %s\n", progname,
 72 			path, strerror(errno));
 73 		goto err;
 74 	}
 75 
 76 	*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
 77 	if (*data == MAP_FAILED) {
 78 		fprintf(stderr, "%s:  Failed to mmap %s:  %s\n", progname, path,
 79 			strerror(errno));
 80 		goto err;
 81 	}
 82 	*len = sb.st_size;
 83 	close(fd);
 84 	return 0;
 85       err:
 86 	close(fd);
 87 	return -1;
 88 }
 89 
 90 int main(int argc, char **argv)
 91 {
 92 	struct sepol_module_package *pkg;
 93 	struct sepol_policy_file *mod, *out;
 94 	char *module = NULL, *file_contexts = NULL, *seusers =
 95 	    NULL, *user_extra = NULL;
 96 	char *fcdata = NULL, *outfile = NULL, *seusersdata =
 97 	    NULL, *user_extradata = NULL;
 98 	char *netfilter_contexts = NULL, *ncdata = NULL;
 99 	size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
100 	int i;
101 
102 	static struct option opts[] = {
103 		{"module", required_argument, NULL, 'm'},
104 		{"fc", required_argument, NULL, 'f'},
105 		{"seuser", required_argument, NULL, 's'},
106 		{"user_extra", required_argument, NULL, 'u'},
107 		{"nc", required_argument, NULL, 'n'},
108 		{"outfile", required_argument, NULL, 'o'},
109 		{"help", 0, NULL, 'h'},
110 		{NULL, 0, NULL, 0}
111 	};
112 
113 	while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
114 		switch (i) {
115 		case 'h':
116 			usage(argv[0]);
117 			exit(0);
118 		case 'm':
119 			if (module) {
120 				fprintf(stderr,
121 					"May not specify more than one module\n");
122 				exit(1);
123 			}
124 			module = strdup(optarg);
125 			if (!module)
126 				exit(1);
127 			break;
128 		case 'f':
129 			if (file_contexts) {
130 				fprintf(stderr,
131 					"May not specify more than one file context file\n");
132 				exit(1);
133 			}
134 			file_contexts = strdup(optarg);
135 			if (!file_contexts)
136 				exit(1);
137 			break;
138 		case 'o':
139 			if (outfile) {
140 				fprintf(stderr,
141 					"May not specify more than one output file\n");
142 				exit(1);
143 			}
144 			outfile = strdup(optarg);
145 			if (!outfile)
146 				exit(1);
147 			break;
148 		case 's':
149 			if (seusers) {
150 				fprintf(stderr,
151 					"May not specify more than one seuser file\n");
152 				exit(1);
153 			}
154 			seusers = strdup(optarg);
155 			if (!seusers)
156 				exit(1);
157 			break;
158 		case 'u':
159 			if (user_extra) {
160 				fprintf(stderr,
161 					"May not specify more than one user_extra file\n");
162 				exit(1);
163 			}
164 			user_extra = strdup(optarg);
165 			if (!user_extra)
166 				exit(1);
167 			break;
168 		case 'n':
169 			if (netfilter_contexts) {
170 				fprintf(stderr,
171 					"May not specify more than one netfilter contexts file\n");
172 				exit(1);
173 			}
174 			netfilter_contexts = strdup(optarg);
175 			if (!netfilter_contexts)
176 				exit(1);
177 			break;
178 		}
179 	}
180 
181 	progname = argv[0];
182 
183 	if (!module || !outfile) {
184 		usage(argv[0]);
185 		exit(0);
186 	}
187 
188 	if (file_contexts) {
189 		if (file_to_data(file_contexts, &fcdata, &fclen))
190 			exit(1);
191 	}
192 
193 	if (seusers) {
194 		if (file_to_data(seusers, &seusersdata, &seuserslen))
195 			exit(1);
196 	}
197 
198 	if (user_extra) {
199 		if (file_to_data(user_extra, &user_extradata, &user_extralen))
200 			exit(1);
201 	}
202 
203 	if (netfilter_contexts) {
204 		if (file_to_data(netfilter_contexts, &ncdata, &nclen))
205 			exit(1);
206 	}
207 
208 	if (file_to_policy_file(module, &mod, "r"))
209 		exit(1);
210 
211 	if (sepol_module_package_create(&pkg)) {
212 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
213 		exit(1);
214 	}
215 
216 	if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
217 		fprintf(stderr,
218 			"%s:  Error while reading policy module from %s\n",
219 			argv[0], module);
220 		exit(1);
221 	}
222 
223 	if (fclen)
224 		sepol_module_package_set_file_contexts(pkg, fcdata, fclen);
225 
226 	if (seuserslen)
227 		sepol_module_package_set_seusers(pkg, seusersdata, seuserslen);
228 
229 	if (user_extra)
230 		sepol_module_package_set_user_extra(pkg, user_extradata,
231 						    user_extralen);
232 
233 	if (nclen)
234 		sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen);
235 
236 	if (file_to_policy_file(outfile, &out, "w"))
237 		exit(1);
238 
239 	if (sepol_module_package_write(pkg, out)) {
240 		fprintf(stderr,
241 			"%s:  Error while writing module package to %s\n",
242 			argv[0], argv[1]);
243 		exit(1);
244 	}
245 
246 	if (fclen)
247 		munmap(fcdata, fclen);
248 	if (nclen)
249 		munmap(ncdata, nclen);
250 	sepol_policy_file_free(mod);
251 	sepol_policy_file_free(out);
252 	sepol_module_package_free(pkg);
253 	free(file_contexts);
254 	free(outfile);
255 	free(module);
256 	exit(0);
257 }

policycoreutils-2.1.13/semodule_package/semodule_unpackage.c

No issues found

  1 #include <sepol/module.h>
  2 #include <getopt.h>
  3 #include <fcntl.h>
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <unistd.h>
  8 #include <sys/types.h>
  9 #include <sys/stat.h>
 10 #include <sys/mman.h>
 11 #include <fcntl.h>
 12 #include <errno.h>
 13 
 14 char *progname = NULL;
 15 extern char *optarg;
 16 
 17 static void usage(char *progname)
 18 {
 19 	printf("usage: %s ppfile modfile [fcfile]\n", progname);
 20 	exit(1);
 21 }
 22 
 23 static int file_to_policy_file(char *filename, struct sepol_policy_file **pf, char *mode)
 24 {
 25 	FILE *f;
 26 
 27 	if (sepol_policy_file_create(pf)) {
 28 		fprintf(stderr, "%s:  Out of memory\n", progname);
 29 		return -1;
 30 	}
 31 
 32 	f = fopen(filename, mode);
 33 	if (!f) {
 34 		fprintf(stderr, "%s:  Could not open file %s:  %s\n", progname, strerror(errno), filename);
 35 		return -1;
 36 	}
 37 	sepol_policy_file_set_fp(*pf, f);
 38 	return 0;
 39 }
 40 
 41 int main(int argc, char **argv)
 42 {
 43 	struct sepol_module_package *pkg;
 44 	struct sepol_policy_file *in, *out;
 45 	FILE *fp;
 46 	size_t len;
 47 	char *ppfile, *modfile, *fcfile = NULL, *fcdata;
 48 
 49 	progname = argv[0];
 50 
 51 	if (argc < 3) {
 52 		usage(progname);
 53 		exit(1);
 54 	}
 55 
 56 	ppfile = argv[1];
 57 	modfile = argv[2];
 58 	if (argc >= 3)
 59 		fcfile = argv[3];
 60 
 61 	if (file_to_policy_file(ppfile, &in, "r"))
 62 		exit(1);
 63 
 64 	if (sepol_module_package_create(&pkg)) {
 65                 fprintf(stderr, "%s:  Out of memory\n", progname);
 66                 exit(1);
 67 	}
 68 
 69 	if (sepol_module_package_read(pkg, in, 0) == -1) {
 70                 fprintf(stderr, "%s:  Error while reading policy module from %s\n",
 71 			progname, ppfile);
 72                 exit(1);
 73 	}
 74 
 75 	if (file_to_policy_file(modfile, &out, "w"))
 76 		exit(1);
 77 
 78         if (sepol_policydb_write(sepol_module_package_get_policy(pkg), out)) {
 79                 fprintf(stderr, "%s:  Error while writing module to %s\n", progname, modfile);
 80                 exit(1);
 81         }
 82 
 83 	sepol_policy_file_free(in);
 84 	sepol_policy_file_free(out);
 85 
 86 	len = sepol_module_package_get_file_contexts_len(pkg);
 87 	if (fcfile && len) {
 88 		fp = fopen(fcfile, "w");
 89 		if (!fp) {
 90 			fprintf(stderr, "%s:  Could not open file %s:  %s\n", progname, strerror(errno), fcfile);
 91 			exit(1);
 92 		}
 93 		fcdata = sepol_module_package_get_file_contexts(pkg);
 94 		if (fwrite(fcdata, 1, len, fp) != len) {
 95 			fprintf(stderr, "%s:  Could not write file %s:  %s\n", progname, strerror(errno), fcfile);
 96 			exit(1);
 97 		}
 98 		fclose(fp);
 99 	}
100 
101 	sepol_module_package_free(pkg);
102 	exit(0);
103 }

policycoreutils-2.1.13/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c

No issues found

  1 /* Authors: Frank Mayer <mayerf@tresys.com>
  2  *   and Karl MacMillan <kmacmillan@tresys.com>
  3  *
  4  * Copyright (C) 2003,2010 Tresys Technology, LLC
  5  *
  6  *	This program is free software; you can redistribute it and/or
  7  *  	modify it under the terms of the GNU General Public License as
  8  *  	published by the Free Software Foundation, version 2.
  9  *
 10  * Adapted from dispol.c.
 11  *
 12  * This program is used by sepolgen-ifgen to get the access for all of
 13  * the attributes in the policy so that it can resolve the
 14  * typeattribute statements in the interfaces.
 15  *
 16  * It outputs the attribute access in a similar format to what sepolgen
 17  * uses to store interface vectors:
 18  *   [Attribute sandbox_x_domain]
 19  *   sandbox_x_domain,samba_var_t,file,ioctl,read,getattr,lock,open
 20  *   sandbox_x_domain,samba_var_t,dir,getattr,search,open
 21  *   sandbox_x_domain,initrc_var_run_t,file,ioctl,read,getattr,lock,open
 22  *
 23  */
 24 
 25 #include <sepol/policydb/policydb.h>
 26 #include <sepol/policydb/avtab.h>
 27 #include <sepol/policydb/util.h>
 28 
 29 #include <stdio.h>
 30 #include <sys/types.h>
 31 #include <sys/stat.h>
 32 #include <fcntl.h>
 33 #include <sys/mman.h>
 34 #include <unistd.h>
 35 
 36 struct val_to_name {
 37 	unsigned int val;
 38 	char *name;
 39 };
 40 
 41 static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
 42 {
 43 	struct val_to_name *v = data;
 44 	perm_datum_t *perdatum;
 45 
 46 	perdatum = (perm_datum_t *) datum;
 47 
 48 	if (v->val == perdatum->s.value) {
 49 		v->name = key;
 50 		return 1;
 51 	}
 52 
 53 	return 0;
 54 }
 55 
 56 int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
 57 		       FILE *fp)
 58 {
 59 	struct val_to_name v;
 60 	class_datum_t *cladatum;
 61 	char *perm = NULL;
 62 	unsigned int i;
 63 	int rc;
 64 	uint32_t tclass = key->target_class;
 65 
 66 	cladatum = policydbp->class_val_to_struct[tclass - 1];
 67 	for (i = 0; i < cladatum->permissions.nprim; i++) {
 68 		if (av & (1 << i)) {
 69 			v.val = i + 1;
 70 			rc = hashtab_map(cladatum->permissions.table,
 71 					 perm_name, &v);
 72 			if (!rc && cladatum->comdatum) {
 73 				rc = hashtab_map(cladatum->comdatum->
 74 						 permissions.table, perm_name,
 75 						 &v);
 76 			}
 77 			if (rc)
 78 				perm = v.name;
 79 			if (perm) {
 80 				fprintf(fp, ",%s", perm);
 81 			}
 82 		}
 83 	}
 84 
 85 	return 0;
 86 }
 87 
 88 static int render_key(avtab_key_t *key, policydb_t *p, FILE *fp)
 89 {
 90 	char *stype, *ttype, *tclass;
 91 	stype = p->p_type_val_to_name[key->source_type - 1];
 92 	ttype = p->p_type_val_to_name[key->target_type - 1];
 93 	tclass = p->p_class_val_to_name[key->target_class - 1];
 94 	if (stype && ttype) {
 95 		fprintf(fp, "%s,%s,%s", stype, ttype, tclass);
 96 	} else {
 97 		fprintf(stderr, "error rendering key\n");
 98 		exit(1);
 99 	}
100 
101 	return 0;
102 }
103 
104 struct callback_data
105 {
106 	uint32_t attr;
107 	policydb_t *policy;
108 	FILE *fp;
109 };
110 
111 int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
112 {
113 	struct callback_data *cb_data = (struct callback_data *)args;
114 
115 	if (key->source_type != cb_data->attr)
116 		return 0;
117 
118 	if (!(key->specified & AVTAB_AV && key->specified & AVTAB_ALLOWED))
119 		return 0;
120 
121 	render_key(key, cb_data->policy, cb_data->fp);
122 	render_access_mask(datum->data, key, cb_data->policy, cb_data->fp);
123 	fprintf(cb_data->fp, "\n");
124 
125 	return 0;
126 }
127 
128 static int attribute_callback(hashtab_key_t key, hashtab_datum_t datum, void *datap)
129 {
130 	struct callback_data *cb_data = (struct callback_data *)datap;
131 	type_datum_t *t = (type_datum_t *)datum;
132 
133 	if (t->flavor == TYPE_ATTRIB) {
134 		fprintf(cb_data->fp, "[Attribute %s]\n", key);
135 		cb_data->attr = t->s.value;
136 		if (avtab_map(&cb_data->policy->te_avtab, output_avrule, cb_data) < 0)
137 			return -1;
138 		if (avtab_map(&cb_data->policy->te_cond_avtab, output_avrule, cb_data) < 0)
139 			return -1;
140 	}
141 
142 	return 0;
143 }
144 
145 static policydb_t *load_policy(const char *filename)
146 {
147 	policydb_t *policydb;
148 	struct policy_file pf;
149 	FILE *fp;
150 	int ret;
151 
152 	fp = fopen(filename, "r");
153 	if (fp == NULL) {
154 		fprintf(stderr, "Can't open '%s':  %s\n",
155 			filename, strerror(errno));
156 		return NULL;
157 	}
158 
159 	policy_file_init(&pf);
160 	pf.type = PF_USE_STDIO;
161 	pf.fp = fp;
162 
163 	policydb = malloc(sizeof(policydb_t));
164 	if (policydb == NULL) {
165 		fprintf(stderr, "Out of memory!\n");
166 		return NULL;
167 	}
168 
169 	if (policydb_init(policydb)) {
170 		fprintf(stderr, "Out of memory!\n");
171 		free(policydb);
172 		return NULL;
173 	}
174 
175 	ret = policydb_read(policydb, &pf, 1);
176 	if (ret) {
177 		fprintf(stderr,
178 			"error(s) encountered while parsing configuration\n");
179 		free(policydb);
180 		return NULL;
181 	}
182 
183 	fclose(fp);
184 
185 	return policydb;
186 
187 }
188 
189 void usage(char *progname)
190 {
191 	printf("usage: %s policy_file out_file\n", progname);
192 }
193 
194 int main(int argc, char **argv)
195 {
196 	policydb_t *p;
197 	struct callback_data cb_data;
198 	FILE *fp;
199 
200 	if (argc != 3) {
201 		usage(argv[0]);
202 		return -1;
203 	}
204 
205 	/* Open the policy. */
206 	p = load_policy(argv[1]);
207 	if (p == NULL)
208 		return -1;
209 
210 	/* Open the output policy. */
211 	fp = fopen(argv[2], "w");
212 	if (fp == NULL) {
213 		fprintf(stderr, "error opening output file\n");
214 		policydb_destroy(p);
215 		free(p);
216 		return -1;
217 	}
218 
219 	/* Find all of the attributes and output their access. */
220 	cb_data.policy = p;
221 	cb_data.fp = fp;
222 
223 	if (hashtab_map(p->p_types.table, attribute_callback, &cb_data)) {
224 		printf("error finding attributes\n");
225 	}
226 
227 	policydb_destroy(p);
228 	free(p);
229 	fclose(fp);
230 
231 	return 0;
232 }

policycoreutils-2.1.13/sepolicy/common.h

Location Tool Test ID Issue
common.h:22:1 cpychecker refcount-too-high py_append_string ob_refcnt of '*obj' is 1 too high
common.h:22:1 cpychecker refcount-too-high py_append_string ob_refcnt of '*obj' is 1 too high
common.h:30:1 cpychecker refcount-too-high py_append_obj ob_refcnt of '*obj' is 1 too high
common.h:30:1 cpychecker refcount-too-high py_append_obj ob_refcnt of '*obj' is 1 too high
 1 #include "Python.h"
 2 
 3 #ifdef UNUSED
 4 #elif defined(__GNUC__)
 5 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
 6 #elif defined(__LCLINT__)
 7 # define UNUSED(x) /*@unused@*/ x
 8 #else
 9 # define UNUSED(x) x
10 #endif
11 
12 #define py_decref(x) { if (x) 	Py_DECREF(x); }
13 
14 static int py_append_string(PyObject *list, const char* value)
15 {
16 	int rt;
17 	PyObject *obj = PyString_FromString(value);
18 	if (!obj) return -1;
19 	rt = PyList_Append(list, obj);
20 	Py_DECREF(obj);
21 	return rt;
22 }
ob_refcnt of '*obj' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

ob_refcnt of '*obj' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

23 24 static int py_append_obj(PyObject *list, PyObject *obj) 25 { 26 int rt; 27 if (!obj) return -1; 28 rt = PyList_Append(list, obj); 29 return rt; 30 }
ob_refcnt of '*obj' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

ob_refcnt of '*obj' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

31 32 static int py_insert_obj(PyObject *dict, const char *name, PyObject *obj) 33 { 34 int rt; 35 if (!obj) return -1; 36 rt = PyDict_SetItemString(dict, name, obj); 37 return rt; 38 } 39 40 static int py_insert_string(PyObject *dict, const char *name, const char* value) 41 { 42 int rt; 43 PyObject *obj = PyString_FromString(value); 44 if (!obj) return -1; 45 rt = PyDict_SetItemString(dict, name, obj); 46 Py_DECREF(obj); 47 return rt; 48 }

policycoreutils-2.1.13/sepolicy/info.c

Location Tool Test ID Issue
info.c:875:2 cpychecker returns-NULL-without-setting-exception info returning (PyObject*)NULL without setting an exception
info.c:882:26 cpychecker mismatching-type-in-format-string wrap_info Mismatching type in call to PyArg_ParseTuple with format code "iz"
info.c:882:26 cpychecker mismatching-type-in-format-string wrap_info Mismatching type in call to PyArg_ParseTuple with format code "iz"
info.c:886:1 cpychecker refcount-too-high wrap_info ob_refcnt of new ref from (unknown) info is 1 too high
  1 /**
  2  *  @file
  3  *  Command line tool to search TE rules.
  4  *
  5  *  @author Frank Mayer  mayerf@tresys.com
  6  *  @author Jeremy A. Mowery jmowery@tresys.com
  7  *  @author Paul Rosenfeld  prosenfeld@tresys.com
  8  *  @author Thomas Liu  <tliu@redhat.com>
  9  *  @author Dan Walsh  <dwalsh@redhat.com>
 10  *
 11  *  Copyright (C) 2003-2008 Tresys Technology, LLC
 12  *
 13  *  This program is free software; you can redistribute it and/or modify
 14  *  it under the terms of the GNU General Public License as published by
 15  *  the Free Software Foundation; either version 2 of the License, or
 16  *  (at your option) any later version.
 17  *
 18  *  This program is distributed in the hope that it will be useful,
 19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  *  GNU General Public License for more details.
 22  *
 23  *  You should have received a copy of the GNU General Public License
 24  *  along with this program; if not, write to the Free Software
 25  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 26  */
 27 
 28 /**
 29  * This is a modified version of seinfo to be used as part of a library for
 30  * Python bindings.
 31  */
 32 
 33 #include "common.h"
 34 #include "policy.h"
 35 
 36 /* libapol */
 37 #include <apol/policy-query.h>
 38 #include <apol/render.h>
 39 #include <apol/util.h>
 40 #include <apol/vector.h>
 41 
 42 /* libqpol */
 43 #include <qpol/policy.h>
 44 #include <qpol/util.h>
 45 
 46 /* other */
 47 #include <errno.h>
 48 #include <stdlib.h>
 49 #include <stdio.h>
 50 #include <string.h>
 51 #include <assert.h>
 52 
 53 #define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC"
 54 
 55 enum input
 56 {
 57 	TYPE, ATTRIBUTE, ROLE, USER, PORT, BOOLEAN,
 58 };
 59 
 60 static int py_insert_long(PyObject *dict, const char *name, int value)
 61 {
 62 	int rt;
 63 	PyObject *obj = PyInt_FromLong(value);
 64 	if (!obj) return -1;
 65 	rt = PyDict_SetItemString(dict, name, obj);
 66 	Py_DECREF(obj);
 67 	return rt;
 68 }
 69 
 70 static int py_insert_bool(PyObject *dict, const char *name, int value)
 71 {
 72 	int rt;
 73 	PyObject *obj = PyBool_FromLong(value);
 74 	if (!obj) return -1;
 75 	rt = PyDict_SetItemString(dict, name, obj);
 76 	Py_DECREF(obj);
 77 	return rt;
 78 }
 79 
 80 /**
 81  * Gets a textual representation of an attribute, and 
 82  * all of that attribute's types.
 83  *
 84  * @param type_datum Reference to sepol type_datum
 85  * @param policydb Reference to a policy
 86  */
 87 static PyObject* get_attr(const qpol_type_t * type_datum, const apol_policy_t * policydb)
 88 {
 89 	PyObject *list = NULL;
 90 	const qpol_type_t *attr_datum = NULL;
 91 	qpol_iterator_t *iter = NULL;
 92 	const char *attr_name = NULL, *type_name = NULL;
 93 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
 94 	unsigned char isattr;
 95 	int error = 0;
 96 	int rt = 0;
 97 	PyObject *dict = PyDict_New(); 
 98 	if (!dict) goto err;
 99 
100 	if (qpol_type_get_name(q, type_datum, &attr_name))
101 		goto err;
102 
103 	if (py_insert_string(dict, "name", attr_name))
104 		goto err;
105 
106 	/* get an iterator over all types this attribute has */
107 	if (qpol_type_get_isattr(q, type_datum, &isattr))
108 		goto err;
109 
110 	if (isattr) {	       /* sanity check */
111 		if (qpol_type_get_type_iter(q, type_datum, &iter))
112 			goto err;
113 		list = PyList_New(0);
114 		if (!list) goto err;
115 		
116 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
117 			if (qpol_iterator_get_item(iter, (void **)&attr_datum))
118 				goto err;
119 			if (qpol_type_get_name(q, attr_datum, &type_name))
120 				goto err;
121 			if (py_append_string(list, type_name))
122 				goto err;
123 		}
124 		qpol_iterator_destroy(&iter);
125 		rt = PyDict_SetItemString(dict, "types", list);
126 		Py_DECREF(list); list = NULL;
127 		if (rt) goto err;
128 	} else		       /* this should never happen */
129 		goto err;
130 	goto cleanup;
131 
132 err:
133 	error = errno;
134 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
135 	py_decref(dict); dict = NULL;
136 	py_decref(list);
137 
138 cleanup:
139 	qpol_iterator_destroy(&iter);
140 	errno =	error;
141 	return dict;
142 }
143 
144 /**
145  * Gets statistics regarding a policy's attributes.
146  * If this function is given a name, it will attempt to
147  * get statistics about a particular attribute; otherwise
148  * the function gets statistics about all of the policy's
149  * attributes.
150  *
151  * @param name Reference to an attribute's name; if NULL,
152  * all object classes will be considered
153  * @param policydb Reference to a policy
154  *
155  * @return 0 on success, < 0 on error.
156  */
157 static PyObject* get_attribs(const char *name, const apol_policy_t * policydb)
158 {
159 	PyObject *obj;
160 	apol_attr_query_t *attr_query = NULL;
161 	apol_vector_t *v = NULL;
162 	const qpol_type_t *type_datum = NULL;
163 	size_t n_attrs, i;
164 	int error = 0;
165 	int rt = 0;
166 	PyObject *list = PyList_New(0);
167 	if (!list) goto err;
168 
169 	/* we are only getting information about 1 attribute */
170 	if (name != NULL) {
171 		attr_query = apol_attr_query_create();
172 		if (!attr_query)
173 			goto err;
174 		if (apol_attr_query_set_attr(policydb, attr_query, name))
175 			goto err;
176 		if (apol_attr_get_by_query(policydb, attr_query, &v))
177 			goto err;
178 		apol_attr_query_destroy(&attr_query);
179 		if (apol_vector_get_size(v) == 0) {
180 			apol_vector_destroy(&v);
181 			errno = EINVAL;
182 			goto err;
183 		}
184 
185 		type_datum = apol_vector_get_element(v, (size_t) 0);
186 		obj = get_attr(type_datum, policydb);
187 		rt = py_append_obj(list, obj);
188 		Py_DECREF(obj);
189 		if (rt) goto err;
190 	} else {
191 		attr_query = apol_attr_query_create();
192 		if (!attr_query)
193 			goto err;
194 		if (apol_attr_get_by_query(policydb, attr_query, &v))
195 			goto err;
196 		apol_attr_query_destroy(&attr_query);
197 		n_attrs = apol_vector_get_size(v);
198 
199 		for (i = 0; i < n_attrs; i++) {
200 			/* get qpol_type_t* item from vector */
201 			type_datum = (qpol_type_t *) apol_vector_get_element(v, (size_t) i);
202 			if (!type_datum)
203 				goto err;
204 			obj = get_attr(type_datum, policydb);
205 			rt = py_append_obj(list, obj);
206 			Py_DECREF(obj);
207 			if (rt) goto err;
208 		}
209 	}
210 	apol_vector_destroy(&v);
211 	goto cleanup;
212 
213 err:
214 	error = errno;
215 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
216 	py_decref(list); list = NULL;
217 
218 cleanup:
219 	apol_attr_query_destroy(&attr_query);
220 	apol_vector_destroy(&v);
221 	errno = error;
222 	return list;
223 }
224 
225 /**
226  * Get a textual representation of a type, and
227  * all of that type's attributes.
228  *
229  * @param type_datum Reference to sepol type_datum
230  * @param policydb Reference to a policy
231  */
232 static PyObject* get_type_attrs(const qpol_type_t * type_datum, const apol_policy_t * policydb)
233 {
234 	qpol_iterator_t *iter = NULL;
235 	const char *attr_name = NULL;
236 	const qpol_type_t *attr_datum = NULL;
237 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
238 	int error = 0;
239 	PyObject *list = PyList_New(0);
240 	if (!list) goto err;
241 
242 	if (qpol_type_get_attr_iter(q, type_datum, &iter))
243 		goto err;
244 
245 	for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
246 		if (qpol_iterator_get_item(iter, (void **)&attr_datum))
247 			goto err;
248 		if (qpol_type_get_name(q, attr_datum, &attr_name))
249 			goto err;
250 		if (py_append_string(list, attr_name))
251 			goto err;
252 	}
253 	goto cleanup;
254 
255 err:
256 	error = errno;
257 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
258 	py_decref(list); list = NULL;
259 
260 cleanup:
261 	qpol_iterator_destroy(&iter);
262 	errno = error;
263 	return list;
264 }
265 
266 static PyObject* get_type( const qpol_type_t * type_datum, const apol_policy_t * policydb) {
267 
268 	PyObject *obj;
269 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
270 	const char *type_name = NULL;
271 	int error = 0;
272 	int rt;
273 	unsigned char isalias, ispermissive, isattr;
274 	PyObject *dict = PyDict_New(); 
275 	if (!dict) goto err;
276 
277 	if (qpol_type_get_name(q, type_datum, &type_name))
278 		goto err;
279 	if (qpol_type_get_isalias(q, type_datum, &isalias))
280 		goto err;
281 	if (qpol_type_get_isattr(q, type_datum, &isattr))
282 		goto err;
283 	if (qpol_type_get_ispermissive(q, type_datum, &ispermissive))
284 		goto err;
285 
286 	if (py_insert_string(dict, "name", type_name))
287 		goto err;
288 
289 	if (py_insert_bool(dict, "permissive", ispermissive))
290 		goto err;
291 
292 	if (!isattr && !isalias) {
293 		obj = get_type_attrs(type_datum, policydb);
294 		rt = py_insert_obj(dict, "attributes", obj);
295 		Py_DECREF(obj);
296 		if (rt) goto err;
297 	}
298 	goto cleanup;
299 
300 err:
301 	error = errno;
302 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
303 	py_decref(dict); dict = NULL;
304 
305 cleanup:
306 	errno = error; 
307 	return dict;
308 }
309 
310 /**
311  * Gets statistics regarding a policy's booleans.
312  * If this function is given a name, it will attempt to
313  * get statistics about a particular boolean; otherwise
314  * the function gets statistics about all of the policy's booleans.
315  *
316  * @param fp Reference to a file to which to print statistics
317  * @param name Reference to a boolean's name; if NULL,
318  * all booleans will be considered
319  * @param expand Flag indicating whether to print each
320  * boolean's default state
321  * @param policydb Reference to a policy
322  *
323  * @return new reference, or NULL (setting an exception)
324  */
325 static PyObject* get_booleans(const char *name, const apol_policy_t * policydb)
326 {
327 	PyObject *dict = NULL;
328 	int error = 0;
329 	int rt = 0;
330 	const char *bool_name = NULL;
331 	int state;
332 	qpol_bool_t *bool_datum = NULL;
333 	qpol_iterator_t *iter = NULL;
334 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
335 	size_t n_bools = 0;
336 	PyObject *list = PyList_New(0);
337 	if (!list) goto err;
338 
339 	if (name != NULL) {
340 		if (qpol_policy_get_bool_by_name(q, name, &bool_datum))
341 			goto err;
342 		if (qpol_bool_get_state(q, bool_datum, &state))
343 			goto err;
344 
345 		dict = PyDict_New(); 
346 		if (!dict) goto err;
347 		if (py_insert_string(dict, "name", name))
348 			goto err;
349 		if (py_insert_bool(dict, "name", state))
350 			goto err;
351 		rt = py_append_obj(list, dict);
352 		Py_DECREF(dict); dict = NULL;
353 		if (rt) goto err;
354 	} else {
355 		if (qpol_policy_get_bool_iter(q, &iter))
356 			goto err;
357 		if (qpol_iterator_get_size(iter, &n_bools))
358 			goto err;
359 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
360 			if (qpol_iterator_get_item(iter, (void **)&bool_datum))
361 				goto err;
362 			if (qpol_bool_get_name(q, bool_datum, &bool_name))
363 				goto err;
364 			if (qpol_bool_get_state(q, bool_datum, &state))
365 				goto err;
366 
367 			dict = PyDict_New(); 
368 			if (!dict) goto err;
369 			if (py_insert_string(dict, "name", bool_name))
370 				goto err;
371 			if (py_insert_bool(dict, "state", state))
372 				goto err;
373 			rt = py_append_obj(list, dict);
374 			Py_DECREF(dict); dict = NULL;
375 			if (rt) goto err;
376 		}
377 		qpol_iterator_destroy(&iter);
378 	}
379 	goto cleanup;
380 
381 err:
382 	error = errno;
383 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
384 	py_decref(list); list = NULL;
385 	py_decref(dict); dict = NULL;
386 
387 cleanup:
388 	qpol_iterator_destroy(&iter);
389 	errno = error; 
390 	return list;
391 }
392 
393 /**
394  * Gets a textual representation of a user, and
395  * all of that user's roles.
396  *
397  * @param type_datum Reference to sepol type_datum
398  * @param policydb Reference to a policy
399  * roles
400  */
401 static PyObject* get_user(const qpol_user_t * user_datum, const apol_policy_t * policydb)
402 {
403 	int error = 0;
404 	int rt;
405 	const qpol_role_t *role_datum = NULL;
406 	qpol_iterator_t *iter = NULL;
407 	const qpol_mls_range_t *range = NULL;
408 	const qpol_mls_level_t *dflt_level = NULL;
409 	apol_mls_level_t *ap_lvl = NULL;
410 	apol_mls_range_t *ap_range = NULL;
411 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
412 	char *tmp = NULL;
413 	const char *user_name, *role_name;
414 	PyObject *dict = NULL;
415 	PyObject *list = PyList_New(0);
416 	if (!list) goto err;
417 
418 	if (qpol_user_get_name(q, user_datum, &user_name))
419 		goto err;
420 
421 	dict = PyDict_New(); 
422 	if (!dict) goto err;
423 
424 	if (py_insert_string(dict, "name", user_name))
425 		goto err;
426 
427 	if (qpol_policy_has_capability(q, QPOL_CAP_MLS)) {
428 		if (qpol_user_get_dfltlevel(q, user_datum, &dflt_level))
429 			goto err;
430 		ap_lvl = apol_mls_level_create_from_qpol_mls_level(policydb, dflt_level);
431 		tmp = apol_mls_level_render(policydb, ap_lvl);
432 		if (!tmp) goto err;
433 		if (py_insert_string(dict, "level", tmp))
434 		    goto err;
435 		free(tmp); tmp = NULL;
436 
437 		if (qpol_user_get_range(q, user_datum, &range))
438 			goto err;
439 		ap_range = apol_mls_range_create_from_qpol_mls_range(policydb, range);
440 		tmp = apol_mls_range_render(policydb, ap_range);
441 		if (!tmp) goto err;
442 		if (py_insert_string(dict, "range", tmp))
443 		    goto err;
444 		free(tmp); tmp=NULL;
445 	}
446 	
447 	if (qpol_user_get_role_iter(q, user_datum, &iter))
448 		goto err;
449 	for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
450 		if (qpol_iterator_get_item(iter, (void **)&role_datum))
451 			goto err;
452 		if (qpol_role_get_name(q, role_datum, &role_name))
453 			goto err;
454 		if (py_append_string(list, role_name))
455 			goto err;
456 	}
457 
458 	rt = py_insert_obj(dict, "roles", list);
459 	Py_DECREF(list); list=NULL;
460 	if (rt) goto err;
461 	goto cleanup;
462 
463 err:
464 	error = errno;
465 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
466 	py_decref(list); list=NULL;
467 	py_decref(dict); dict=NULL;
468 
469 cleanup:
470 	free(tmp);
471 	qpol_iterator_destroy(&iter);
472 	apol_mls_level_destroy(&ap_lvl);
473 	apol_mls_range_destroy(&ap_range);
474 	errno = error;
475 	return dict;
476 }
477 
478 /**
479  * Gets statistics regarding a policy's users.
480  * If this function is given a name, it will attempt to
481  * get statistics about a particular user; otherwise
482  * the function gets statistics about all of the policy's
483  * users.
484  *
485  * @param name Reference to a user's name; if NULL,
486  * all users will be considered
487  * @param policydb Reference to a policy
488  *
489  * @return 0 on success, < 0 on error.
490  */
491 static PyObject*  get_users(const char *name, const apol_policy_t * policydb)
492 {
493 	qpol_iterator_t *iter = NULL;
494 	const qpol_user_t *user_datum = NULL;
495 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
496 	int error = 0;
497 	int rt;
498 	PyObject *obj;
499 	PyObject *list = PyList_New(0);
500 	if (!list) goto err;
501 
502 	if (name != NULL) {
503 		if (qpol_policy_get_user_by_name(q, name, &user_datum)) {
504 			errno = EINVAL;
505 			goto err;
506 		}
507 		obj = get_user(user_datum, policydb);
508 		rt = py_append_obj(list, obj);
509 		Py_DECREF(obj);
510 		if (rt) goto err;
511 	} else {
512 		if (qpol_policy_get_user_iter(q, &iter))
513 			goto err;
514 
515 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
516 			if (qpol_iterator_get_item(iter, (void **)&user_datum))
517 				goto err;
518 			obj = get_user(user_datum, policydb);
519 			rt = py_append_obj(list, obj);
520 			Py_DECREF(obj);
521 			if (rt) goto err;
522 		}
523 		qpol_iterator_destroy(&iter);
524 	}
525 	goto cleanup;
526 
527 err:
528 	error = errno;
529 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
530 	py_decref(list); list = NULL;
531 
532 cleanup:
533 	qpol_iterator_destroy(&iter);
534 	errno = error;
535 	return list;
536 }
537 
538 /**
539  * get a textual representation of a role, and 
540  * all of that role's types.
541  *
542  * @param type_datum Reference to sepol type_datum
543  * @param policydb Reference to a policy
544  * types
545  */
546 static PyObject* get_role(const qpol_role_t * role_datum, const apol_policy_t * policydb)
547 {
548 	const char *role_name = NULL, *type_name = NULL;
549 	const qpol_role_t *dom_datum = NULL;
550 	const qpol_type_t *type_datum = NULL;
551 	qpol_iterator_t *iter = NULL;
552 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
553 	size_t n_dom = 0, n_types = 0;
554 	int error = 0;
555 	int rt;
556 	PyObject *list = NULL;
557 	PyObject *dict = PyDict_New();
558 	if (!dict) goto err;
559 
560 	if (qpol_role_get_name(q, role_datum, &role_name))
561 		goto err;
562 	if (py_insert_string(dict, "name", role_name))
563 		goto err;
564 
565 	if (qpol_role_get_dominate_iter(q, role_datum, &iter))
566 		goto err;
567 	if (qpol_iterator_get_size(iter, &n_dom))
568 		goto err;
569 	if ((int)n_dom > 0) {
570 		list = PyList_New(0);
571 		if (!list) goto err;
572 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
573 			if (qpol_iterator_get_item(iter, (void **)&dom_datum))
574 				goto err;
575 			if (qpol_role_get_name(q, dom_datum, &role_name))
576 				goto err;
577 			if (py_append_string(list, role_name))
578 				goto err;
579 		}
580 		rt = py_insert_obj(dict, "roles", list);
581 		Py_DECREF(list); list = NULL;
582 		if (rt) goto err;
583 	}
584 	qpol_iterator_destroy(&iter);
585 	
586 	if (qpol_role_get_type_iter(q, role_datum, &iter))
587 		goto err;
588 	if (qpol_iterator_get_size(iter, &n_types))
589 		goto err;
590 	if ((int)n_types > 0) {
591 		list = PyList_New(0);
592 		if (!list) goto err;
593 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
594 			if (qpol_iterator_get_item(iter, (void **)&type_datum))
595 				goto err;
596 			if (qpol_type_get_name(q, type_datum, &type_name))
597 				goto err;
598 			if (py_append_string(list, type_name))
599 				goto err;
600 		}
601 		rt = py_insert_obj(dict, "types", list);
602 		Py_DECREF(list); list = NULL;
603 		if (rt) goto err;
604 	}
605 	goto cleanup;
606 
607 err:
608 	error = errno;
609 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
610 	py_decref(list); list = NULL;
611 	py_decref(dict); dict = NULL;
612 
613 cleanup:
614 	qpol_iterator_destroy(&iter);
615 	errno =	error;
616 	return dict;
617 }
618 
619 /**
620  * Get statistics regarding a policy's ports.
621  * If this function is given a name, it will attempt to
622  * get statistics about a particular port; otherwise
623  * the function get statistics about all of the policy's ports.
624  *
625  * @param name Reference to an port's name; if NULL,
626  * all ports will be considered
627  * @param policydb Reference to a policy
628  *
629  * @return 0 on success, < 0 on error.
630  */
631 static PyObject*  get_ports(const char *num, const apol_policy_t * policydb)
632 {
633 	const qpol_portcon_t *portcon = NULL;
634 	qpol_iterator_t *iter = NULL;
635 	uint16_t low_port, high_port;
636 	uint8_t ocon_proto;
637 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
638 	const qpol_context_t *ctxt = NULL;
639 	const char *proto_str = NULL;
640 	const char *type = NULL;
641 	const apol_mls_range_t *range = NULL;
642 	char *range_str = NULL;
643 	apol_context_t *c = NULL;
644 	int error = 0;
645 	int rt = 0;
646 	PyObject *dict = NULL;
647 	PyObject *list = PyList_New(0);
648 	if (!list) goto err;
649 
650 	if (qpol_policy_get_portcon_iter(q, &iter))
651 		goto err;
652 
653 	for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
654 		if (qpol_iterator_get_item(iter, (void **)&portcon))
655 			goto err;
656 		if (qpol_portcon_get_low_port(q, portcon, &low_port))
657 			goto err;
658 		if (qpol_portcon_get_high_port(q, portcon, &high_port))
659 			goto err;
660 		if (qpol_portcon_get_protocol(q, portcon, &ocon_proto))
661 			goto err;
662 		if (num) {
663 			if (atoi(num) < low_port || atoi(num) > high_port)
664 				continue;
665 		}
666 
667 		if ((ocon_proto != IPPROTO_TCP) &&
668 		    (ocon_proto != IPPROTO_UDP)) 
669 			goto err;
670 
671 		if (qpol_portcon_get_context(q, portcon, &ctxt)) {
672 			PyErr_SetString(PyExc_RuntimeError, "Could not get for port context.");
673 			goto err;
674 		}
675 
676 		if ((proto_str = apol_protocol_to_str(ocon_proto)) == NULL) {
677 			PyErr_SetString(PyExc_RuntimeError, "Invalid protocol for port");
678 			goto err;
679 		}
680 
681 		if ((c = apol_context_create_from_qpol_context(policydb, ctxt)) == NULL) {
682 			goto err;
683 		}
684 		
685 		if((type = apol_context_get_type(c)) == NULL) {
686 			apol_context_destroy(&c);
687 			goto err;
688 		}
689 			
690 		dict = PyDict_New(); 
691 		if (!dict) goto err;
692 		if (py_insert_string(dict, "type", type))
693 			goto err;
694 
695 		if((range = apol_context_get_range(c)) == NULL) {
696 			goto err;
697 		}
698 			
699 		range_str = apol_mls_range_render(policydb, range);
700 		if (range_str == NULL) {
701 			goto err;
702 		}
703 		if (py_insert_string(dict, "range", range_str))
704 			goto err;
705 
706 		if (py_insert_string(dict, "protocol", proto_str))
707 			goto err;
708 
709 		if (py_insert_long(dict, "high", high_port))
710 			goto err;
711 
712 		if (py_insert_long(dict, "low", low_port))
713 			goto err;
714 
715 		rt = py_append_obj(list, dict);
716 		Py_DECREF(dict); dict = NULL;
717 		if (rt) goto err;
718 	}
719 	goto cleanup;
720 
721 err:
722 	error = errno;
723 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
724 	py_decref(list); list = NULL;
725 	py_decref(dict); dict = NULL;
726 
727 cleanup:
728 	free(range_str);
729 	apol_context_destroy(&c);
730 	qpol_iterator_destroy(&iter);
731 	errno = error;
732 	return list;
733 }
734 
735 /**
736  * Get statistics regarding a policy's roles.
737  * If this function is given a name, it will attempt to
738  * get statistics about a particular role; otherwise
739  * the function get statistics about all of the policy's roles.
740  *
741  * @param name Reference to an role's name; if NULL,
742  * all roles will be considered
743  * @param policydb Reference to a policy
744  *
745  * @return 0 on success, < 0 on error.
746  */
747 static PyObject*  get_roles(const char *name, const apol_policy_t * policydb)
748 {
749 	const qpol_role_t *role_datum = NULL;
750 	qpol_iterator_t *iter = NULL;
751 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
752 	int error = 0;
753 	int rt;
754 	PyObject *obj;
755 	PyObject *list = PyList_New(0);
756 	if (!list) goto err;
757 
758 	if (name != NULL) {
759 		if (qpol_policy_get_role_by_name(q, name, &role_datum)) {
760 			errno = EINVAL;
761 			goto err;
762 		}
763 		obj = get_role(role_datum, policydb);
764 		rt = py_append_obj(list, obj);
765 		Py_DECREF(obj); 
766 		if (rt) goto err;
767 	} else {
768 		if (qpol_policy_get_role_iter(q, &iter))
769 			goto err;
770 
771 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
772 			if (qpol_iterator_get_item(iter, (void **)&role_datum))
773 				goto err;
774 			obj = get_role(role_datum, policydb);
775 			rt = py_append_obj(list, obj);
776 			Py_DECREF(obj); 
777 			if (rt) goto err;
778 		}
779 		qpol_iterator_destroy(&iter);
780 	}
781 	goto cleanup;
782 
783 err:
784 	error = errno;
785 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
786 	py_decref(list); list = NULL;
787 
788 cleanup:
789 	qpol_iterator_destroy(&iter);
790 	errno = error;
791 	return list;
792 }
793 
794 /**
795  * Get statistics regarding a policy's types.
796  * If this function is given a name, it will attempt to
797  * print statistics about a particular type; otherwise
798  * the function prints statistics about all of the policy's types.
799  *
800  * @param name Reference to a type's name; if NULL,
801  * all object classes will be considered
802  * @param policydb Reference to a policy
803  *
804  * @return 0 on success, < 0 on error.
805  */
806 static PyObject* get_types(const char *name, const apol_policy_t * policydb)
807 {
808 	const qpol_type_t *type_datum = NULL;
809 	qpol_iterator_t *iter = NULL;
810 	qpol_policy_t *q = apol_policy_get_qpol(policydb);
811 	int error = 0;
812 	int rt;
813 	PyObject *obj;
814 	PyObject *list = PyList_New(0);
815 	if (!list) goto err;
816 	/* if name was provided, only print that name */
817 	if (name != NULL) {
818 		if (qpol_policy_get_type_by_name(q, name, &type_datum)) {
819 			errno = EINVAL;
820 			goto err;
821 		}
822 		obj = get_type(type_datum, policydb);
823 		rt = py_append_obj(list, obj);
824 		Py_DECREF(obj); 
825 		if (rt) goto err;
826 	} else {
827 		if (qpol_policy_get_type_iter(q, &iter))
828 			goto err;
829 
830 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
831 			if (qpol_iterator_get_item(iter, (void **)&type_datum))
832 				goto err;
833 			obj = get_type(type_datum, policydb);
834 			rt = py_append_obj(list, obj);
835 			Py_DECREF(obj); 
836 			if (rt) goto err;
837 		}
838 	}
839 	goto cleanup;
840 
841 err:
842 	error = errno;
843 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
844 	py_decref(list); list = NULL;
845 
846 cleanup:
847 	qpol_iterator_destroy(&iter);
848 	errno =	error;
849 	return list;
850 }
851 
852 PyObject* info( int type, const char *name)
853 {
854 	PyObject* output = NULL;
855 
856 	/* display requested info */
857 	if (type == TYPE)
858 		output = get_types(name, policy);
859 
860 	if (type == ATTRIBUTE)
861 		output = get_attribs(name, policy);
862 
863 	if (type == ROLE)
864 		output = get_roles(name, policy);
865 
866 	if (type == USER)
867 		output = get_users(name, policy);
868 
869 	if (type == BOOLEAN)
870 		output = get_booleans(name, policy);
871 
872 	if (type == PORT)
873 		output = get_ports(name, policy);
874 
875 	return output;
returning (PyObject*)NULL without setting an exception
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

876 } 877 878 PyObject *wrap_info(PyObject *UNUSED(self), PyObject *args){ 879 unsigned int type; 880 char *name; 881 882 if (!PyArg_ParseTuple(args, "iz", &type, &name))
Mismatching type in call to PyArg_ParseTuple with format code "iz"
argument 4 ("&name") had type "char * *" but was expecting "const char * *" for format code "z"
(emitted by cpychecker)
Mismatching type in call to PyArg_ParseTuple with format code "iz"
argument 3 ("&type") had type "unsigned int *" (pointing to 32 bits) but was expecting "int *" (pointing to 32 bits) for format code "i"
(emitted by cpychecker)
883 return NULL; 884 885 return Py_BuildValue("N",info(type, name)); 886 }
ob_refcnt of new ref from (unknown) info is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

887 888 void init_info (PyObject *m) { 889 PyModule_AddIntConstant(m, "ATTRIBUTE", ATTRIBUTE); 890 PyModule_AddIntConstant(m, "PORT", PORT); 891 PyModule_AddIntConstant(m, "ROLE", ROLE); 892 PyModule_AddIntConstant(m, "TYPE", TYPE); 893 PyModule_AddIntConstant(m, "USER", USER); 894 PyModule_AddIntConstant(m, "BOOLEAN", BOOLEAN); 895 }

policycoreutils-2.1.13/sepolicy/policy.c

Location Tool Test ID Issue
policy.c:78:1 cpychecker refcount-too-low wrap_policy ob_refcnt of return value is 1 too low
 1 /**
 2  *  @file
 3  *  Python bindings to search SELinux Policy rules.
 4  *
 5  *  @author Dan Walsh  <dwalsh@redhat.com>
 6  *
 7  *  Copyright (C) 2012 Red Hat, INC
 8  *
 9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #include "Python.h"
25 
26 #ifdef UNUSED
27 #elif defined(__GNUC__)
28 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
29 #elif defined(__LCLINT__)
30 # define UNUSED(x) /*@unused@*/ x
31 #else
32 # define UNUSED(x) x
33 #endif
34 
35 #include "policy.h"
36 apol_policy_t *policy = NULL;
37 
38 /* other */
39 #include <errno.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <assert.h>
44 
45 #define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC"
46 
47 PyObject *wrap_policy(PyObject *UNUSED(self), PyObject *args){
48     const char *policy_file;
49     apol_vector_t *mod_paths = NULL;
50     apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC;
51     apol_policy_path_t *pol_path = NULL;
52     
53     if (!PyArg_ParseTuple(args, "z", &policy_file))
54 	    return NULL;
55 
56     if (policy) 
57 	    apol_policy_destroy(&policy);
58 
59     int policy_load_options = 0;
60 	    
61     pol_path = apol_policy_path_create(path_type, policy_file, mod_paths);
62     if (!pol_path) {
63 	    apol_vector_destroy(&mod_paths);
64 	    PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
65 	    return NULL;
66     }
67     apol_vector_destroy(&mod_paths);
68     
69     policy_load_options |= QPOL_POLICY_OPTION_MATCH_SYSTEM;
70     policy = apol_policy_create_from_policy_path(pol_path, policy_load_options, NULL, NULL);
71     apol_policy_path_destroy(&pol_path);
72     if (!policy) {
73 	    PyErr_SetString(PyExc_RuntimeError,strerror(errno));
74 	    return NULL;
75     }
76 
77     return Py_None;
78 }
ob_refcnt of return value is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

79 80 static PyMethodDef methods[] = { 81 {"policy", (PyCFunction) wrap_policy, METH_VARARGS, 82 "Initialize SELinux policy for use with search and info"}, 83 {"info", (PyCFunction) wrap_info, METH_VARARGS, 84 "Return SELinux policy info about types, attributes, roles, users"}, 85 {"search", (PyCFunction) wrap_search, METH_VARARGS, 86 "Search SELinux Policy for allow, neverallow, auditallow, dontaudit and transition records"}, 87 {NULL, NULL, 0, NULL} /* sentinel */ 88 }; 89 90 void init_policy() { 91 PyObject *m; 92 m = Py_InitModule("_policy", methods); 93 init_info(m); 94 }

policycoreutils-2.1.13/sepolicy/search.c

Location Tool Test ID Issue
search.c:106:1 cpychecker refcount-too-low py_tuple_insert_obj ob_refcnt of '*obj' is 1 too low
search.c:215:2 cpychecker null-ptr-dereference get_ra_results dereferencing NULL (dict->ob_refcnt) at search.c:215
search.c:215:2 clang-analyzer Access to field 'ob_refcnt' results in a dereference of a null pointer (loaded from variable 'dict')
search.c:397:1 cpychecker refcount-too-low get_te_results ob_refcnt of return value is 1 too low
search.c:454:3 clang-analyzer Value stored to 'error' is never read
search.c:562:1 cpychecker refcount-too-low get_ft_results ob_refcnt of return value is 1 too low
search.c:784:1 cpychecker refcount-too-low get_av_results ob_refcnt of return value is 1 too low
search.c:824:2 clang-analyzer Value stored to 'pol_opt' is never read
search.c:929:6 cpychecker null-ptr-dereference search dereferencing NULL (MEM[(struct PyVarObject *)output].ob_size) at search.c:929
search.c:929:6 clang-analyzer Access to field 'ob_size' results in a dereference of a null pointer (loaded from variable 'output')
search.c:934:1 cpychecker refcount-too-low search ob_refcnt of return value is 1 too low
search.c:934:1 cpychecker refcount-too-high search ob_refcnt of new ref from (unknown) get_av_results is 1 too high
search.c:967:1 cpychecker refcount-too-high wrap_search ob_refcnt of new ref from (unknown) search is 1 too high
  1 // Author: Thomas Liu <tliu@redhat.com>
  2 
  3 /**
  4  *  @file
  5  *  Python bindings used to search TE rules.
  6  *
  7  *  @author Thomas Liu  <tliu@redhat.com>
  8  *  @author Dan Walsh  <dwalsh@redhat.com>
  9  *  Copyright (C) 2012 Red Hat, inc
 10  *
 11  *  Sections copied from sesearch.c in setools package
 12  *  @author Frank Mayer  mayerf@tresys.com
 13  *  @author Jeremy A. Mowery jmowery@tresys.com
 14  *  @author Paul Rosenfeld  prosenfeld@tresys.com
 15  *  Copyright (C) 2003-2008 Tresys Technology, LLC
 16  *
 17  *  This program is free software; you can redistribute it and/or modify
 18  *  it under the terms of the GNU General Public License as published by
 19  *  the Free Software Foundation; either version 2 of the License, or
 20  *  (at your option) any later version.
 21  *
 22  *  This program is distributed in the hope that it will be useful,
 23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 25  *  GNU General Public License for more details.
 26  *
 27  *  You should have received a copy of the GNU General Public License
 28  *  along with this program; if not, write to the Free Software
 29  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 30  */
 31 
 32 /**
 33  * This is a modified version of sesearch to be used as part of a sepython library for
 34  * Python bindings.
 35  */
 36 
 37 #include "common.h"
 38 #include "policy.h"
 39 
 40 /* libapol */
 41 #include <apol/policy-query.h>
 42 #include <apol/render.h>
 43 #include <apol/util.h>
 44 #include <apol/vector.h>
 45 
 46 /* libqpol*/
 47 #include <qpol/policy.h>
 48 #include <qpol/policy_extend.h>
 49 #include <qpol/syn_rule_query.h>
 50 #include <qpol/util.h>
 51 
 52 /* other */
 53 #include <errno.h>
 54 #include <stdlib.h>
 55 #include <stdio.h>
 56 #include <assert.h>
 57 #include <getopt.h>
 58 #include <string.h>
 59 #include <stdbool.h>
 60 
 61 #define COPYRIGHT_INFO "Copyright (C) 2012 Red Hat, Inc, Tresys Technology, LLC"
 62 
 63 enum opt_values
 64 {
 65 	RULE_NEVERALLOW = 256, RULE_AUDIT, RULE_AUDITALLOW, RULE_DONTAUDIT,
 66 	RULE_ROLE_ALLOW, RULE_ROLE_TRANS, RULE_RANGE_TRANS, RULE_ALL,
 67 	EXPR_ROLE_SOURCE, EXPR_ROLE_TARGET
 68 };
 69 
 70 ;
 71 
 72 typedef struct options
 73 {
 74 	char *src_name;
 75 	char *tgt_name;
 76 	char *src_role_name;
 77 	char *tgt_role_name;
 78 	char *class_name;
 79 	char *permlist;
 80 	char *bool_name;
 81 	apol_vector_t *class_vector;
 82 	bool all;
 83 	bool lineno;
 84 	bool semantic;
 85 	bool indirect;
 86 	bool allow;
 87 	bool nallow;
 88 	bool auditallow;
 89 	bool dontaudit;
 90 	bool type;
 91 	bool rtrans;
 92 	bool role_allow;
 93 	bool role_trans;
 94 	bool useregex;
 95 	bool show_cond;
 96 	apol_vector_t *perm_vector;
 97 } options_t;
 98 
 99 static int py_tuple_insert_obj(PyObject *tuple, int pos, PyObject *obj)
100 {
101 	int rt;
102 	if (!obj) return -1;
103 	rt = PyTuple_SetItem(tuple, pos, obj);
104 	Py_DECREF(obj);
105 	return rt;
106 }
ob_refcnt of '*obj' is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

107 108 static int perform_ra_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) 109 { 110 apol_role_allow_query_t *raq = NULL; 111 int error = 0; 112 113 if (!policy || !opt || !v) { 114 ERR(policy, "%s", strerror(EINVAL)); 115 errno = EINVAL; 116 return -1; 117 } 118 119 if (!opt->role_allow && !opt->all) { 120 *v = NULL; 121 return 0; /* no search to do */ 122 } 123 124 raq = apol_role_allow_query_create(); 125 if (!raq) { 126 ERR(policy, "%s", strerror(ENOMEM)); 127 errno = ENOMEM; 128 return -1; 129 } 130 131 apol_role_allow_query_set_regex(policy, raq, opt->useregex); 132 if (opt->src_role_name) { 133 if (apol_role_allow_query_set_source(policy, raq, opt->src_role_name)) { 134 error = errno; 135 goto err; 136 } 137 } 138 if (opt->tgt_role_name) 139 if (apol_role_allow_query_set_target(policy, raq, opt->tgt_role_name)) { 140 error = errno; 141 goto err; 142 } 143 144 if (apol_role_allow_get_by_query(policy, raq, v)) { 145 error = errno; 146 goto err; 147 } 148 apol_role_allow_query_destroy(&raq); 149 return 0; 150 151 err: 152 apol_vector_destroy(v); 153 apol_role_allow_query_destroy(&raq); 154 ERR(policy, "%s", strerror(error)); 155 errno = error; 156 return -1; 157 } 158 159 static PyObject* get_ra_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output) 160 { 161 size_t i, num_rules = 0; 162 qpol_policy_t *q; 163 const qpol_role_allow_t *rule = NULL; 164 const char *tmp; 165 PyObject *obj, *dict=NULL; 166 const qpol_role_t *role = NULL; 167 int error = 0; 168 errno = EINVAL; 169 int rt; 170 171 if (!policy || !v) { 172 errno = EINVAL; 173 goto err; 174 } 175 176 if (!(num_rules = apol_vector_get_size(v))) 177 return NULL; 178 179 q = apol_policy_get_qpol(policy); 180 181 for (i = 0; i < num_rules; i++) { 182 dict = PyDict_New(); 183 if (!dict) goto err; 184 if (!(rule = apol_vector_get_element(v, i))) 185 goto err; 186 187 if (qpol_role_allow_get_source_role(q, rule, &role)) { 188 goto err; 189 } 190 if (qpol_role_get_name(q, role, &tmp)) { 191 goto err; 192 } 193 obj = PyString_FromString(tmp); 194 if (py_insert_obj(dict, "source", obj)) 195 goto err; 196 197 if (qpol_role_allow_get_target_role(q, rule, &role)) { 198 goto err; 199 } 200 if (qpol_role_get_name(q, role, &tmp)) { 201 goto err; 202 } 203 obj = PyString_FromString(tmp); 204 if (py_insert_obj(dict, "target", obj)) 205 goto err; 206 207 rt = py_append_obj(output, dict); 208 Py_DECREF(dict); dict=NULL; 209 if (rt) goto err; 210 } 211 goto cleanup; 212 err: 213 error = errno; 214 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 215 Py_DECREF(dict); dict=NULL;
dereferencing NULL (dict->ob_refcnt) at search.c:215
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Access to field 'ob_refcnt' results in a dereference of a null pointer (loaded from variable 'dict')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

216 217 cleanup: 218 errno = error; 219 return output; 220 } 221 222 static int perform_te_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) 223 { 224 apol_terule_query_t *teq = NULL; 225 unsigned int rules = 0; 226 int error = 0; 227 228 if (!policy || !opt || !v) { 229 PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL)); 230 errno = EINVAL; 231 return -1; 232 } 233 234 if (opt->all || opt->type) { 235 rules = (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER); 236 } else { 237 *v = NULL; 238 return 0; /* no search to do */ 239 } 240 241 teq = apol_terule_query_create(); 242 if (!teq) { 243 PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); 244 errno = ENOMEM; 245 return -1; 246 } 247 248 apol_terule_query_set_rules(policy, teq, rules); 249 apol_terule_query_set_regex(policy, teq, opt->useregex); 250 251 if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { 252 if (apol_syn_terule_get_by_query(policy, teq, v)) { 253 goto err; 254 } 255 } else { 256 if (apol_terule_get_by_query(policy, teq, v)) { 257 goto err; 258 } 259 } 260 261 apol_terule_query_destroy(&teq); 262 return 0; 263 264 err: 265 error = errno; 266 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 267 apol_vector_destroy(v); 268 apol_terule_query_destroy(&teq); 269 errno = error; 270 return -1; 271 } 272 273 static PyObject* get_te_results(const apol_policy_t * policy, const options_t * opt, const apol_vector_t * v, PyObject *output) 274 { 275 int error = 0; 276 int rt = 0; 277 PyObject *obj, *dict=NULL, *tuple = NULL; 278 qpol_policy_t *q; 279 uint32_t rule_type = 0; 280 const qpol_type_t *type; 281 size_t i, num_rules = 0; 282 const qpol_terule_t *rule = NULL; 283 char *tmp = NULL, *rule_str = NULL, *expr = NULL; 284 qpol_iterator_t *iter = NULL; 285 const qpol_cond_t *cond = NULL; 286 uint32_t enabled = 0, list = 0; 287 const char *tmp_name; 288 const qpol_class_t *obj_class = NULL; 289 290 if (!policy || !v) { 291 errno = EINVAL; 292 goto err; 293 } 294 295 if (!(num_rules = apol_vector_get_size(v))) 296 return NULL; 297 298 q = apol_policy_get_qpol(policy); 299 300 for (i = 0; i < num_rules; i++) { 301 dict = PyDict_New(); 302 if (!dict) goto err; 303 if (!(rule = apol_vector_get_element(v, i))) 304 goto err; 305 if (opt->show_cond) { 306 if (qpol_terule_get_cond(q, rule, &cond)) 307 goto err; 308 if (qpol_terule_get_is_enabled(q, rule, &enabled)) 309 goto err; 310 if (cond) { 311 if (qpol_terule_get_which_list(q, rule, &list)) 312 goto err; 313 if (qpol_cond_get_expr_node_iter(q, cond, &iter)) 314 goto err; 315 316 qpol_iterator_destroy(&iter); 317 tuple = PyTuple_New(2); 318 if (!tuple) goto err; 319 tmp_name = apol_cond_expr_render(policy, cond); 320 obj = PyString_FromString(tmp_name); 321 if (py_tuple_insert_obj(tuple, 1, obj)) 322 goto err; 323 obj = PyBool_FromLong(enabled); 324 if (py_tuple_insert_obj(tuple, 2, obj)) 325 goto err; 326 rt = py_insert_obj(dict, "boolean", tuple); 327 Py_DECREF(tuple); tuple = NULL; 328 if (rt) goto err; 329 } 330 } 331 332 if (qpol_terule_get_rule_type(q, rule, &rule_type)) 333 goto err; 334 335 if (!(rule_type &= (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER))) { 336 PyErr_SetString(PyExc_RuntimeError,"Invalid TE rule type"); 337 errno = EINVAL; 338 goto err; 339 } 340 if (!(tmp_name = apol_rule_type_to_str(rule_type))) { 341 PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string"); 342 errno = EINVAL; 343 goto err; 344 } 345 346 if (py_insert_string(dict, "type", tmp_name)) 347 goto err; 348 349 if (qpol_terule_get_source_type(q, rule, &type)) 350 goto err; 351 if (qpol_type_get_name(q, type, &tmp_name)) 352 goto err; 353 if (py_insert_string(dict, "source", tmp_name)) 354 goto err; 355 356 if (qpol_terule_get_target_type(q, rule, &type)) 357 goto err; 358 if (qpol_type_get_name(q, type, &tmp_name)) 359 goto err; 360 if (py_insert_string(dict, "target", tmp_name)) 361 goto err; 362 363 if (qpol_terule_get_object_class(q, rule, &obj_class)) 364 goto err; 365 if (qpol_class_get_name(q, obj_class, &tmp_name)) 366 goto err; 367 if (py_insert_string(dict, "class", tmp_name)) 368 goto err; 369 370 if (qpol_terule_get_default_type(q, rule, &type)) 371 goto err; 372 if (qpol_type_get_name(q, type, &tmp_name)) 373 goto err; 374 if (py_insert_string(dict, "transtype", tmp_name)) 375 goto err; 376 377 rt = py_append_obj(output, dict); 378 dict = NULL; 379 if(rt) goto err; 380 381 free(rule_str); rule_str = NULL; 382 free(expr); expr = NULL; 383 } 384 goto cleanup; 385 386 err: 387 error = errno; 388 py_decref(dict); 389 py_decref(tuple); 390 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 391 cleanup: 392 free(tmp); 393 free(rule_str); 394 free(expr); 395 errno = error; 396 return output; 397 }
ob_refcnt of return value is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

398 399 static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) 400 { 401 apol_filename_trans_query_t *ftq = NULL; 402 size_t i; 403 int error = 0; 404 405 if (!policy || !opt || !v) { 406 PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL)); 407 errno = EINVAL; 408 return -1; 409 } 410 411 if (!opt->type && !opt->all) { 412 *v = NULL; 413 return 0; /* no search to do */ 414 } 415 416 ftq = apol_filename_trans_query_create(); 417 if (!ftq) { 418 PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); 419 errno = ENOMEM; 420 return -1; 421 } 422 423 apol_filename_trans_query_set_regex(policy, ftq, opt->useregex); 424 if (opt->src_name) { 425 if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name, opt->indirect)) { 426 goto err; 427 } 428 } 429 430 if (opt->tgt_name) { 431 if (apol_filename_trans_query_set_target(policy, ftq, opt->tgt_name, opt->indirect)) { 432 goto err; 433 } 434 } 435 if (opt->class_name) { 436 if (opt->class_vector == NULL) { 437 if (apol_filename_trans_query_append_class(policy, ftq, opt->class_name)) { 438 goto err; 439 } 440 } else { 441 for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) { 442 char *class_name; 443 class_name = apol_vector_get_element(opt->class_vector, i); 444 if (!class_name) 445 continue; 446 if (apol_filename_trans_query_append_class(policy, ftq, class_name)) { 447 goto err; 448 } 449 } 450 } 451 } 452 453 if (apol_filename_trans_get_by_query(policy, ftq, v)) { 454 error = errno;
Value stored to 'error' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

455 } 456 457 apol_filename_trans_query_destroy(&ftq); 458 return 0; 459 460 err: 461 error = errno; 462 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 463 apol_vector_destroy(v); 464 apol_filename_trans_query_destroy(&ftq); 465 errno = error; 466 return -1; 467 } 468 469 static PyObject* get_ft_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *list) 470 { 471 PyObject *dict = NULL; 472 size_t i, num_filename_trans = 0; 473 const char *tmp_name; 474 int error = 0; 475 int rt; 476 const qpol_filename_trans_t *filename_trans = NULL; 477 const qpol_class_t *obj_class = NULL; 478 char *tmp = NULL, *filename_trans_str = NULL, *expr = NULL; 479 qpol_policy_t *q; 480 const qpol_type_t *type = NULL; 481 482 if (!policy || !v) { 483 errno = EINVAL; 484 goto err; 485 } 486 487 if (!(num_filename_trans = apol_vector_get_size(v))) 488 return NULL; 489 490 q = apol_policy_get_qpol(policy); 491 492 for (i = 0; i < num_filename_trans; i++) { 493 if (!(filename_trans = apol_vector_get_element(v, i))) 494 goto err; 495 496 dict = PyDict_New(); 497 if (!dict) goto err; 498 499 if (py_insert_string(dict, "type", "type_transition")) 500 goto err; 501 502 /* source type */ 503 if (qpol_filename_trans_get_source_type(q, filename_trans, &type)) { 504 goto err; 505 } 506 if (qpol_type_get_name(q, type, &tmp_name)) { 507 goto err; 508 } 509 510 if (py_insert_string(dict, "source", tmp_name)) 511 goto err; 512 513 if (qpol_filename_trans_get_target_type(q, filename_trans, &type)) 514 goto err; 515 516 if (qpol_type_get_name(q, type, &tmp_name)) 517 goto err; 518 519 if (py_insert_string(dict, "target", tmp_name)) 520 goto err; 521 522 if (qpol_filename_trans_get_object_class(q, filename_trans, &obj_class)) 523 goto err; 524 525 if (qpol_class_get_name(q, obj_class, &tmp_name)) 526 goto err; 527 528 if (py_insert_string(dict, "class", tmp_name)) 529 goto err; 530 531 if (qpol_filename_trans_get_default_type(q, filename_trans, &type)) 532 goto err; 533 if (qpol_type_get_name(q, type, &tmp_name)) 534 goto err; 535 if (py_insert_string(dict, "transtype", tmp_name)) 536 goto err; 537 538 if (! qpol_filename_trans_get_filename(q, filename_trans, &tmp_name)) { 539 if (py_insert_string(dict, "filename", tmp_name)) 540 goto err; 541 } 542 543 rt = py_append_obj(list, dict); 544 dict = NULL; 545 if (rt) goto err; 546 547 free(filename_trans_str); filename_trans_str = NULL; 548 free(expr); expr = NULL; 549 } 550 goto cleanup; 551 552 err: 553 error = errno; 554 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 555 py_decref(dict); 556 cleanup: 557 free(tmp); 558 free(filename_trans_str); 559 free(expr); 560 errno = error; 561 return list; 562 }
ob_refcnt of return value is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

563 564 static int perform_av_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) 565 { 566 apol_avrule_query_t *avq = NULL; 567 unsigned int rules = 0; 568 int error = 0; 569 char *tmp = NULL, *tok = NULL, *s = NULL; 570 571 if (!policy || !opt || !v) { 572 PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL)); 573 errno = EINVAL; 574 return -1; 575 } 576 577 if (!opt->all && !opt->allow && !opt->nallow && !opt->auditallow && !opt->dontaudit) { 578 *v = NULL; 579 return 0; /* no search to do */ 580 } 581 582 avq = apol_avrule_query_create(); 583 if (!avq) { 584 PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); 585 errno = ENOMEM; 586 return -1; 587 } 588 589 if (opt->allow || opt->all) 590 rules |= QPOL_RULE_ALLOW; 591 if ((opt->nallow || opt->all) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_NEVERALLOW)) 592 rules |= QPOL_RULE_NEVERALLOW; 593 if (opt->auditallow || opt->all) 594 rules |= QPOL_RULE_AUDITALLOW; 595 if (opt->dontaudit || opt->all) 596 rules |= QPOL_RULE_DONTAUDIT; 597 apol_avrule_query_set_rules(policy, avq, rules); 598 apol_avrule_query_set_regex(policy, avq, opt->useregex); 599 if (opt->src_name) 600 apol_avrule_query_set_source(policy, avq, opt->src_name, opt->indirect); 601 if (opt->tgt_name) 602 apol_avrule_query_set_target(policy, avq, opt->tgt_name, opt->indirect); 603 if (opt->bool_name) 604 apol_avrule_query_set_bool(policy, avq, opt->bool_name); 605 if (opt->class_name) { 606 if (opt->class_vector == NULL) { 607 if (apol_avrule_query_append_class(policy, avq, opt->class_name)) { 608 goto err; 609 } 610 } else { 611 size_t i; 612 for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) { 613 char *class_name; 614 class_name = apol_vector_get_element(opt->class_vector, i); 615 if (!class_name) 616 continue; 617 if (apol_avrule_query_append_class(policy, avq, class_name)) { 618 goto err; 619 } 620 } 621 } 622 } 623 624 if (opt->permlist) { 625 tmp = strdup(opt->permlist); 626 for (tok = strtok(tmp, ","); tok; tok = strtok(NULL, ",")) { 627 if (apol_avrule_query_append_perm(policy, avq, tok)) { 628 goto err; 629 } 630 if ((s = strdup(tok)) == NULL || apol_vector_append(opt->perm_vector, s) < 0) { 631 goto err; 632 } 633 s = NULL; 634 } 635 free(tmp); 636 } 637 638 if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { 639 if (apol_syn_avrule_get_by_query(policy, avq, v)) { 640 goto err; 641 } 642 } else { 643 if (apol_avrule_get_by_query(policy, avq, v)) { 644 goto err; 645 } 646 } 647 648 apol_avrule_query_destroy(&avq); 649 return 0; 650 651 err: 652 error = errno; 653 PyErr_SetString(PyExc_RuntimeError,strerror(error)); 654 apol_vector_destroy(v); 655 apol_avrule_query_destroy(&avq); 656 free(tmp); 657 free(s); 658 errno = error; 659 return -1; 660 } 661 662 static PyObject* get_av_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output) 663 { 664 PyObject *dict = NULL; 665 PyObject *permlist = NULL; 666 int rt; 667 int error = 0; 668 qpol_policy_t *q; 669 size_t i, num_rules = 0; 670 const qpol_avrule_t *rule = NULL; 671 char *tmp = NULL, *rule_str = NULL, *expr = NULL; 672 qpol_iterator_t *iter = NULL; 673 uint32_t enabled = 0; 674 675 if (!policy || !v) { 676 errno = EINVAL; 677 goto err; 678 } 679 680 if (!(num_rules = apol_vector_get_size(v))) 681 return NULL; 682 683 q = apol_policy_get_qpol(policy); 684 685 for (i = 0; i < num_rules; i++) { 686 if (!(rule = apol_vector_get_element(v, i))) 687 goto err; 688 689 if (qpol_avrule_get_is_enabled(q, rule, &enabled)) 690 goto err; 691 if (!enabled) 692 continue; 693 694 const qpol_type_t *type; 695 const char *tmp_name; 696 uint32_t rule_type = 0; 697 698 const qpol_class_t *obj_class = NULL; 699 700 dict = PyDict_New(); 701 if (!dict) goto err; 702 703 if (qpol_avrule_get_rule_type(q, rule, &rule_type)) 704 goto err; 705 706 if (!(tmp_name = apol_rule_type_to_str(rule_type))) { 707 PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string"); 708 goto err; 709 } 710 711 if (py_insert_string(dict, "type", tmp_name)) 712 goto err; 713 714 if (qpol_avrule_get_source_type(q, rule, &type)) { 715 goto err; 716 } 717 718 if (qpol_type_get_name(q, type, &tmp_name)) { 719 goto err; 720 } 721 722 if (py_insert_string(dict, "source", tmp_name)) 723 goto err; 724 725 if (qpol_avrule_get_target_type(q, rule, &type)) { 726 goto err; 727 } 728 if (qpol_type_get_name(q, type, &tmp_name)) { 729 goto err; 730 } 731 732 if (py_insert_string(dict, "target", tmp_name)) 733 goto err; 734 735 if (qpol_avrule_get_object_class(q, rule, &obj_class)) { 736 goto err; 737 } 738 if (qpol_class_get_name(q, obj_class, &tmp_name)) { 739 goto err; 740 } 741 742 if (py_insert_string(dict, "class", tmp_name)) 743 goto err; 744 745 if (qpol_avrule_get_perm_iter(q, rule, &iter)) { 746 goto err; 747 } 748 749 permlist = PyList_New(0); 750 if (! permlist) goto err; 751 752 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { 753 const char *perm_name = NULL; 754 qpol_iterator_get_item(iter, (void **)&perm_name); 755 if (py_append_string(permlist, perm_name)) 756 goto err; 757 } 758 759 rt = PyDict_SetItemString(dict, "permlist", permlist); 760 Py_DECREF(permlist); 761 if (rt) goto err; 762 763 rt = py_append_obj(output, dict); 764 Py_DECREF(dict); dict=NULL; 765 if (rt) goto err; 766 767 free(rule_str); rule_str = NULL; 768 free(expr); expr = NULL; 769 } 770 goto cleanup; 771 772 err: 773 error = errno; 774 PyErr_SetString(PyExc_RuntimeError,strerror(errno)); 775 py_decref(dict); 776 py_decref(permlist); 777 778 cleanup: 779 free(tmp); 780 free(rule_str); 781 free(expr); 782 errno = error; 783 return output; 784 }
ob_refcnt of return value is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

785 786 PyObject* search(bool allow, 787 bool neverallow, 788 bool auditallow, 789 bool dontaudit, 790 bool transition, 791 bool role_allow, 792 const char *src_name, 793 const char *tgt_name, 794 const char *class_name, 795 const char *permlist 796 ) 797 { 798 options_t cmd_opts; 799 PyObject *output = NULL; 800 apol_vector_t *v = NULL; 801 802 memset(&cmd_opts, 0, sizeof(cmd_opts)); 803 cmd_opts.indirect = true; 804 cmd_opts.allow = allow; 805 cmd_opts.nallow = neverallow; 806 cmd_opts.auditallow = auditallow; 807 cmd_opts.dontaudit = dontaudit; 808 cmd_opts.type = transition; 809 cmd_opts.role_allow = role_allow; 810 if (src_name) 811 cmd_opts.src_name = strdup(src_name); 812 if (tgt_name) 813 cmd_opts.tgt_name = strdup(tgt_name); 814 if (class_name) 815 cmd_opts.class_name = strdup(class_name); 816 if (permlist){ 817 cmd_opts.perm_vector = apol_vector_create(free); 818 cmd_opts.permlist = strdup(permlist); 819 } 820 int pol_opt = 0; 821 if (!(cmd_opts.nallow || cmd_opts.all)) 822 pol_opt |= QPOL_POLICY_OPTION_NO_NEVERALLOWS; 823 824 pol_opt |= QPOL_POLICY_OPTION_MATCH_SYSTEM;
Value stored to 'pol_opt' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

825 826 /* handle regex for class name */ 827 if (cmd_opts.useregex && cmd_opts.class_name != NULL) { 828 cmd_opts.class_vector = apol_vector_create(NULL); 829 apol_vector_t *qpol_matching_classes = NULL; 830 apol_class_query_t *regex_match_query = apol_class_query_create(); 831 apol_class_query_set_regex(policy, regex_match_query, 1); 832 apol_class_query_set_class(policy, regex_match_query, cmd_opts.class_name); 833 if (apol_class_get_by_query(policy, regex_match_query, &qpol_matching_classes)) { 834 apol_class_query_destroy(&regex_match_query); 835 PyErr_SetString(PyExc_RuntimeError,"Query failed"); 836 goto cleanup; 837 } 838 const qpol_class_t *class = NULL; 839 size_t i; 840 for (i = 0; i < apol_vector_get_size(qpol_matching_classes); ++i) { 841 const char *class_name; 842 class = apol_vector_get_element(qpol_matching_classes, i); 843 if (!class) 844 break; 845 qpol_class_get_name(apol_policy_get_qpol(policy), class, &class_name); 846 apol_vector_append(cmd_opts.class_vector, (void *)class_name); 847 } 848 if (!apol_vector_get_size(qpol_matching_classes)) { 849 apol_vector_destroy(&qpol_matching_classes); 850 apol_class_query_destroy(&regex_match_query); 851 PyErr_SetString(PyExc_RuntimeError,"No classes match expression"); 852 goto cleanup; 853 } 854 apol_vector_destroy(&qpol_matching_classes); 855 apol_class_query_destroy(&regex_match_query); 856 } 857 858 if (!cmd_opts.semantic && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { 859 if (qpol_policy_build_syn_rule_table(apol_policy_get_qpol(policy))) { 860 apol_policy_destroy(&policy); 861 PyErr_SetString(PyExc_RuntimeError,"Query failed"); 862 goto cleanup; 863 } 864 } 865 866 /* if syntactic rules are not available always do semantic search */ 867 if (!qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { 868 cmd_opts.semantic = 1; 869 } 870 871 /* supress line numbers if doing semantic search or not available */ 872 if (cmd_opts.semantic || !qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_LINE_NUMBERS)) { 873 cmd_opts.lineno = 0; 874 } 875 if (perform_av_query(policy, &cmd_opts, &v)) { 876 goto cleanup; 877 } 878 output = PyList_New(0); 879 if (!output) 880 goto cleanup; 881 882 if (v) { 883 get_av_results(policy, v, output); 884 } 885 886 apol_vector_destroy(&v); 887 if (perform_te_query(policy, &cmd_opts, &v)) { 888 goto cleanup; 889 } 890 if (v) { 891 get_te_results(policy, &cmd_opts, v, output); 892 } 893 894 if (cmd_opts.all || cmd_opts.type) { 895 apol_vector_destroy(&v); 896 if (perform_ft_query(policy, &cmd_opts, &v)) { 897 goto cleanup; 898 } 899 900 if (v) { 901 get_ft_results(policy, v, output); 902 } 903 } 904 905 if (cmd_opts.all || cmd_opts.role_allow) { 906 apol_vector_destroy(&v); 907 if (perform_ra_query(policy, &cmd_opts, &v)) { 908 goto cleanup; 909 } 910 911 if (v) { 912 get_ra_results(policy, v, output); 913 } 914 } 915 916 apol_vector_destroy(&v); 917 918 cleanup: 919 free(cmd_opts.src_name); 920 free(cmd_opts.tgt_name); 921 free(cmd_opts.class_name); 922 free(cmd_opts.permlist); 923 free(cmd_opts.bool_name); 924 free(cmd_opts.src_role_name); 925 free(cmd_opts.tgt_role_name); 926 apol_vector_destroy(&cmd_opts.perm_vector); 927 apol_vector_destroy(&cmd_opts.class_vector); 928 929 if (PyList_GET_SIZE(output) == 0) {
dereferencing NULL (MEM[(struct PyVarObject *)output].ob_size) at search.c:929
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Access to field 'ob_size' results in a dereference of a null pointer (loaded from variable 'output')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

930 Py_DECREF(output); 931 return Py_None; 932 } 933 return output; 934 }
ob_refcnt of return value is 1 too low
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

ob_refcnt of new ref from (unknown) get_av_results is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

935 936 static int Dict_ContainsInt(PyObject *dict, const char *key){ 937 PyObject *item = PyDict_GetItemString(dict, key); 938 if (item) 939 return PyInt_AsLong(item); 940 return false; 941 } 942 943 static const char *Dict_ContainsString(PyObject *dict, const char *key){ 944 PyObject *item = PyDict_GetItemString(dict, key); 945 if (item) 946 return PyString_AsString(item); 947 return NULL; 948 } 949 950 PyObject *wrap_search(PyObject *UNUSED(self), PyObject *args){ 951 PyObject *dict; 952 if (!PyArg_ParseTuple(args, "O", &dict)) 953 return NULL; 954 int allow = Dict_ContainsInt(dict, "allow"); 955 int neverallow = Dict_ContainsInt(dict, "neverallow"); 956 int auditallow = Dict_ContainsInt(dict, "auditallow"); 957 int dontaudit = Dict_ContainsInt(dict, "dontaudit"); 958 int transition = Dict_ContainsInt(dict, "transition"); 959 int role_allow = Dict_ContainsInt(dict, "role_allow"); 960 961 const char *src_name = Dict_ContainsString(dict, "source"); 962 const char *tgt_name = Dict_ContainsString(dict, "target"); 963 const char *class_name = Dict_ContainsString(dict, "class"); 964 const char *permlist = Dict_ContainsString(dict, "permlist"); 965 966 return Py_BuildValue("N",search(allow, neverallow, auditallow, dontaudit, transition, role_allow, src_name, tgt_name, class_name, permlist)); 967 }
ob_refcnt of new ref from (unknown) search is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

policycoreutils-2.1.13/sestatus/sestatus.c

No issues found

  1 /*
  2  * Copyright 1999-2004 Gentoo Technologies, Inc.
  3  * Distributed under the terms of the GNU General Public License v2
  4  * $Header: /home/cvsroot/gentoo-projects/hardened/policycoreutils-extra/src/sestatus.c,v 1.10 2004/03/26 19:25:52 pebenito Exp $
  5  * Patch provided by Steve Grubb
  6  */
  7 
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <string.h>
 11 #include <errno.h>
 12 #include <selinux/selinux.h>
 13 #include <selinux/get_default_type.h>
 14 #include <sys/types.h>
 15 #include <sys/stat.h>
 16 #include <dirent.h>
 17 #include <unistd.h>
 18 #include <libgen.h>
 19 #include <ctype.h>
 20 
 21 #define PROC_BASE "/proc"
 22 #define MAX_CHECK 50
 23 #define CONF "/etc/sestatus.conf"
 24 
 25 /* conf file sections */
 26 #define PROCS "[process]"
 27 #define FILES "[files]"
 28 
 29 /* buffer size for cmp_cmdline */
 30 #define BUFSIZE 255
 31 
 32 /* column to put the output (must be a multiple of 8) */
 33 static unsigned int COL = 32;
 34 
 35 extern char *selinux_mnt;
 36 
 37 int cmp_cmdline(const char *command, int pid)
 38 {
 39 
 40 	char buf[BUFSIZE];
 41 	char filename[BUFSIZE];
 42 
 43 	memset(buf, '\0', BUFSIZE);
 44 
 45 	/* first read the proc entry */
 46 	sprintf(filename, "%s/%d/exe", PROC_BASE, pid);
 47 
 48 	if (readlink(filename, buf, BUFSIZE) < 0)
 49 		return 0;
 50 
 51 	if (buf[BUFSIZE - 1] != '\0')
 52 		buf[BUFSIZE - 1] = '\0';
 53 
 54 	/* check if this is the command we're looking for. */
 55 	if (strcmp(command, buf) == 0)
 56 		return 1;
 57 	else
 58 		return 0;
 59 }
 60 
 61 int pidof(const char *command)
 62 {
 63 /* inspired by killall5.c from psmisc */
 64 	DIR *dir;
 65 	struct dirent *de;
 66 	int pid, ret = -1, self = getpid();
 67 
 68 	if (!(dir = opendir(PROC_BASE))) {
 69 		perror(PROC_BASE);
 70 		return -1;
 71 	}
 72 
 73 	while ((de = readdir(dir)) != NULL) {
 74 		errno = 0;
 75 		pid = (int)strtol(de->d_name, (char **)NULL, 10);
 76 		if (errno || pid == 0 || pid == self)
 77 			continue;
 78 		if (cmp_cmdline(command, pid)) {
 79 			ret = pid;
 80 			break;
 81 		}
 82 	}
 83 
 84 	closedir(dir);
 85 	return ret;
 86 }
 87 
 88 void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
 89 {
 90 
 91 	FILE *fp = fopen(CONF, "r");
 92 	char buf[255], *bufp;
 93 	int buf_len, section = -1;
 94 	int proclen = strlen(PROCS);
 95 	int filelen = strlen(FILES);
 96 
 97 	if (fp == NULL) {
 98 		printf("\nUnable to open %s.\n", CONF);
 99 		return;
100 	}
101 
102 	while (!feof(fp)) {
103 		if (!fgets(buf, sizeof buf, fp))
104 			break;
105 
106 		buf_len = strlen(buf);
107 		if (buf[buf_len - 1] == '\n')
108 			buf[buf_len - 1] = 0;
109 
110 		bufp = buf;
111 		while (*bufp && isspace(*bufp)) {
112 			bufp++;
113 			buf_len--;
114 		}
115 
116 		if (*bufp == '#')
117 			/* skip comments */
118 			continue;
119 
120 		if (*bufp) {
121 			if (!(*bufp))
122 				goto out;
123 
124 			if (strncmp(bufp, PROCS, proclen) == 0)
125 				section = 0;
126 			else if (strncmp(bufp, FILES, filelen) == 0)
127 				section = 1;
128 			else {
129 				switch (section) {
130 				case 0:
131 					if (*npc >= MAX_CHECK)
132 						break;
133 					pc[*npc] =
134 					    (char *)malloc((buf_len) *
135 							   sizeof(char));
136 					memcpy(pc[*npc], bufp, buf_len);
137 					(*npc)++;
138 					bufp = NULL;
139 					break;
140 				case 1:
141 					if (*nfc >= MAX_CHECK)
142 						break;
143 					fc[*nfc] =
144 					    (char *)malloc((buf_len) *
145 							   sizeof(char));
146 					memcpy(fc[*nfc], bufp, buf_len);
147 					(*nfc)++;
148 					bufp = NULL;
149 					break;
150 				default:
151 					/* ignore lines before a section */
152 					printf("Line not in a section: %s.\n",
153 					       buf);
154 					break;
155 				}
156 			}
157 		}
158 	}
159       out:
160 	fclose(fp);
161 	return;
162 }
163 
164 void printf_tab(const char *outp)
165 {
166 	char buf[20];
167 	snprintf(buf, sizeof(buf), "%%-%us", COL);
168 	printf(buf, outp);
169 
170 }
171 
172 int main(int argc, char **argv)
173 {
174 	/* these vars are reused several times */
175 	int rc, opt, i, c, size;
176 	char *context, *root_path;
177 
178 	/* files that need context checks */
179 	char *fc[MAX_CHECK];
180 	char *cterm = ttyname(0);
181 	int nfc = 0;
182 	struct stat m;
183 
184 	/* processes that need context checks */
185 	char *pc[MAX_CHECK];
186 	int npc = 0;
187 
188 	/* booleans */
189 	char **bools;
190 	int nbool;
191 
192 	int verbose = 0;
193 	int show_bools = 0;
194 
195 	/* policy */
196 	const char *pol_name, *root_dir;
197 	char *pol_path;
198 
199 
200 	while (1) {
201 		opt = getopt(argc, argv, "vb");
202 		if (opt == -1)
203 			break;
204 		switch (opt) {
205 		case 'v':
206 			verbose = 1;
207 			break;
208 		case 'b':
209 			show_bools = 1;
210 			break;
211 		default:
212 			/* invalid option */
213 			printf("\nUsage: %s [OPTION]\n\n", basename(argv[0]));
214 			printf("  -v  Verbose check of process and file contexts.\n");
215 			printf("  -b  Display current state of booleans.\n");
216 			printf("\nWithout options, show SELinux status.\n");
217 			return -1;
218 		}
219 	}
220 	printf_tab("SELinux status:");
221 	rc = is_selinux_enabled();
222 
223 	switch (rc) {
224 	case 1:
225 		printf("enabled\n");
226 		break;
227 	case 0:
228 		printf("disabled\n");
229 		return 0;
230 		break;
231 	default:
232 		printf("unknown (%s)\n", strerror(errno));
233 		return 0;
234 		break;
235 	}
236 
237 	printf_tab("SELinuxfs mount:");
238 	if (selinux_mnt != NULL) {
239 		printf("%s\n", selinux_mnt);
240 	} else {
241 		printf("not mounted\n\n");
242 		printf("Please mount selinuxfs for proper results.\n");
243 		return -1;
244 	}
245 
246 	printf_tab("SELinux root directory:");
247 	if ((root_dir = selinux_path()) != NULL) {
248 		/* The path has a trailing '/' so remove it */
249 		size = strlen(root_dir);
250 		root_path = malloc(size);
251 		if (!root_path) {
252 			printf("malloc error (%s)\n", strerror(errno));
253 			return -1;
254 		}
255 		memset(root_path, 0, size);
256 		strncpy(root_path, root_dir, (size-1)) ;
257 		printf("%s\n", root_path);
258 		free(root_path);
259 	} else {
260 			printf("error (%s)\n", strerror(errno));
261 		return -1;
262 	}
263 
264 	/* Dump all the path information */
265 	printf_tab("Loaded policy name:");
266 	pol_path = strdup(selinux_policy_root());
267 	if (pol_path) {
268 		pol_name = basename(pol_path);
269 		puts(pol_name);
270 		free(pol_path);
271 	} else {
272 		printf("error (%s)\n", strerror(errno));
273 	}
274 
275 	printf_tab("Current mode:");
276 	rc = security_getenforce();
277 	switch (rc) {
278 	case 1:
279 		printf("enforcing\n");
280 		break;
281 	case 0:
282 		printf("permissive\n");
283 		break;
284 	default:
285 		printf("unknown (%s)\n", strerror(errno));
286 		break;
287 	}
288 
289 	printf_tab("Mode from config file:");
290 	if (selinux_getenforcemode(&rc) == 0) {
291 		switch (rc) {
292 		case 1:
293 			printf("enforcing\n");
294 			break;
295 		case 0:
296 			printf("permissive\n");
297 			break;
298 		case -1:
299 			printf("disabled\n");
300 			break;
301 		}
302 	} else {
303 		printf("error (%s)\n", strerror(errno));
304 	}
305 
306 	printf_tab("Policy MLS status:");
307 	rc = is_selinux_mls_enabled();
308 	switch (rc) {
309 		case 0:
310 			printf("disabled\n");
311 			break;
312 		case 1:
313 			printf("enabled\n");
314 			break;
315 		default:
316 			printf("error (%s)\n", strerror(errno));
317 			break;
318 	}
319 
320 	printf_tab("Policy deny_unknown status:");
321 	rc = security_deny_unknown();
322 	switch (rc) {
323 		case 0:
324 			printf("allowed\n");
325 			break;
326 		case 1:
327 			printf("denied\n");
328 			break;
329 		default:
330 			printf("error (%s)\n", strerror(errno));
331 			break;
332 	}
333 
334 	rc = security_policyvers();
335 	printf_tab("Max kernel policy version:");
336 	if (rc < 0)
337 		printf("unknown (%s)\n", strerror(errno));
338 	else
339 		printf("%d\n", rc);
340 
341 
342 	if (show_bools) {
343 		/* show booleans */
344 		if (security_get_boolean_names(&bools, &nbool) >= 0) {
345 			printf("\nPolicy booleans:\n");
346 
347 			for (i = 0; i < nbool; i++) {
348 				if (strlen(bools[i]) + 1 > COL)
349 					COL = strlen(bools[i]) + 1;
350 			}
351 			for (i = 0; i < nbool; i++) {
352 				printf_tab(bools[i]);
353 
354 				rc = security_get_boolean_active(bools[i]);
355 				switch (rc) {
356 				case 1:
357 					printf("on");
358 					break;
359 				case 0:
360 					printf("off");
361 					break;
362 				default:
363 					printf("unknown (%s)", strerror(errno));
364 					break;
365 				}
366 				c = security_get_boolean_pending(bools[i]);
367 				if (c != rc)
368 					switch (c) {
369 					case 1:
370 						printf(" (activate pending)");
371 						break;
372 					case 0:
373 						printf(" (inactivate pending)");
374 						break;
375 					default:
376 						printf(" (pending error: %s)",
377 						       strerror(errno));
378 						break;
379 					}
380 				printf("\n");
381 
382 				/* free up the booleans */
383 				free(bools[i]);
384 			}
385 			free(bools);
386 		}
387 	}
388 	/* only show contexts if -v is given */
389 	if (!verbose)
390 		return 0;
391 
392 	load_checks(pc, &npc, fc, &nfc);
393 
394 	printf("\nProcess contexts:\n");
395 
396 	printf_tab("Current context:");
397 	if (getcon(&context) >= 0) {
398 		printf("%s\n", context);
399 		freecon(context);
400 	} else
401 		printf("unknown (%s)\n", strerror(errno));
402 
403 	printf_tab("Init context:");
404 	if (getpidcon(1, &context) >= 0) {
405 		printf("%s\n", context);
406 		freecon(context);
407 	} else
408 		printf("unknown (%s)\n", strerror(errno));
409 
410 	for (i = 0; i < npc; i++) {
411 		rc = pidof(pc[i]);
412 		if (rc > 0) {
413 			if (getpidcon(rc, &context) < 0)
414 				continue;
415 
416 			printf_tab(pc[i]);
417 			printf("%s\n", context);
418 			freecon(context);
419 		}
420 	}
421 
422 	printf("\nFile contexts:\n");
423 
424 	/* controlling term */
425 	printf_tab("Controlling terminal:");
426 	if (lgetfilecon(cterm, &context) >= 0) {
427 		printf("%s\n", context);
428 		freecon(context);
429 	} else {
430 		printf("unknown (%s)\n", strerror(errno));
431 	}
432 
433 	for (i = 0; i < nfc; i++) {
434 		if (lgetfilecon(fc[i], &context) >= 0) {
435 			printf_tab(fc[i]);
436 
437 			/* check if this is a symlink */
438 			if (lstat(fc[i], &m)) {
439 				printf
440 				    ("%s (could not check link status (%s)!)\n",
441 				     context, strerror(errno));
442 				freecon(context);
443 				continue;
444 			}
445 			if (S_ISLNK(m.st_mode)) {
446 				/* print link target context */
447 				printf("%s -> ", context);
448 				freecon(context);
449 
450 				if (getfilecon(fc[i], &context) >= 0) {
451 					printf("%s\n", context);
452 					freecon(context);
453 				} else {
454 					printf("unknown (%s)\n",
455 					       strerror(errno));
456 				}
457 			} else {
458 				printf("%s\n", context);
459 				freecon(context);
460 			}
461 		}
462 	}
463 
464 	return 0;
465 }

policycoreutils-2.1.13/setfiles/restore.c

Location Tool Test ID Issue
restore.c:62:3 gcc missing-braces restore_init missing braces around initializer
restore.c:62:3 gcc missing-braces restore_init (near initialization for 'selinux_opts[0].')
restore.c:684:10 clang-analyzer Function call argument is an uninitialized value
  1 #include "restore.h"
  2 #include <glob.h>
  3 #include <selinux/context.h>
  4 
  5 #define SKIP -2
  6 #define ERR -1
  7 #define MAX_EXCLUDES 1000
  8 
  9 /*
 10  * The hash table of associations, hashed by inode number.
 11  * Chaining is used for collisions, with elements ordered
 12  * by inode number in each bucket.  Each hash bucket has a dummy 
 13  * header.
 14  */
 15 #define HASH_BITS 16
 16 #define HASH_BUCKETS (1 << HASH_BITS)
 17 #define HASH_MASK (HASH_BUCKETS-1)
 18 
 19 /*
 20  * An association between an inode and a context.
 21  */
 22 typedef struct file_spec {
 23 	ino_t ino;		/* inode number */
 24 	char *con;		/* matched context */
 25 	char *file;		/* full pathname */
 26 	struct file_spec *next;	/* next association in hash bucket chain */
 27 } file_spec_t;
 28 
 29 struct edir {
 30 	char *directory;
 31 	size_t size;
 32 };
 33 
 34 
 35 static file_spec_t *fl_head;
 36 static int filespec_add(ino_t ino, const security_context_t con, const char *file);
 37 struct restore_opts *r_opts = NULL;
 38 static void filespec_destroy(void);
 39 static void filespec_eval(void);
 40 static int excludeCtr = 0;
 41 static struct edir excludeArray[MAX_EXCLUDES];
 42 
 43 void remove_exclude(const char *directory)
 44 {
 45 	int i = 0;
 46 	for (i = 0; i < excludeCtr; i++) {
 47 		if (strcmp(directory, excludeArray[i].directory) == 0) {
 48 			free(excludeArray[i].directory);
 49 			if (i != excludeCtr-1)
 50 				excludeArray[i] = excludeArray[excludeCtr-1];
 51 			excludeCtr--;
 52 			return;
 53 		}
 54 	}
 55 	return;
 56 }
 57 
 58 void restore_init(struct restore_opts *opts)
 59 {	
 60 	r_opts = opts;
 61 	struct selinux_opt selinux_opts[] = {
 62 		{ SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
missing braces around initializer
(emitted by gcc)
(near initialization for 'selinux_opts[0].')
(emitted by gcc)
63 { SELABEL_OPT_PATH, r_opts->selabel_opt_path } 64 }; 65 r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 2); 66 if (!r_opts->hnd) { 67 perror(r_opts->selabel_opt_path); 68 exit(1); 69 } 70 } 71 72 void restore_finish() 73 { 74 int i; 75 for (i = 0; i < excludeCtr; i++) { 76 free(excludeArray[i].directory); 77 } 78 } 79 80 static int match(const char *name, struct stat *sb, char **con) 81 { 82 if (!(r_opts->hard_links) && !S_ISDIR(sb->st_mode) && (sb->st_nlink > 1)) { 83 fprintf(stderr, "Warning! %s refers to a file with more than one hard link, not fixing hard links.\n", 84 name); 85 return -1; 86 } 87 88 if (NULL != r_opts->rootpath) { 89 if (0 != strncmp(r_opts->rootpath, name, r_opts->rootpathlen)) { 90 fprintf(stderr, "%s: %s is not located in %s\n", 91 r_opts->progname, name, r_opts->rootpath); 92 return -1; 93 } 94 name += r_opts->rootpathlen; 95 } 96 97 if (r_opts->rootpath != NULL && name[0] == '\0') 98 /* this is actually the root dir of the alt root */ 99 return selabel_lookup_raw(r_opts->hnd, con, "/", sb->st_mode); 100 else 101 return selabel_lookup_raw(r_opts->hnd, con, name, sb->st_mode); 102 } 103 static int restore(FTSENT *ftsent, int recurse) 104 { 105 char *my_file = strdupa(ftsent->fts_path); 106 int ret = -1; 107 security_context_t curcon = NULL, newcon = NULL; 108 float progress; 109 if (match(my_file, ftsent->fts_statp, &newcon) < 0) { 110 if ((errno == ENOENT) && (!recurse)) 111 fprintf(stderr, "%s: Warning no default label for %s\n", r_opts->progname, my_file); 112 113 /* Check for no matching specification. */ 114 return (errno == ENOENT) ? 0 : -1; 115 } 116 117 if (r_opts->progress) { 118 r_opts->count++; 119 if (r_opts->count % STAR_COUNT == 0) { 120 if (r_opts->progress == 1) { 121 fprintf(stdout, "*"); 122 } else { 123 if (r_opts->nfile > 0) { 124 progress = (r_opts->count < r_opts->nfile) ? (100.0 * r_opts->count / r_opts->nfile) : 100; 125 fprintf(stdout, "\r%-.1f%%", progress); 126 } 127 } 128 fflush(stdout); 129 } 130 } 131 132 /* 133 * Try to add an association between this inode and 134 * this specification. If there is already an association 135 * for this inode and it conflicts with this specification, 136 * then use the last matching specification. 137 */ 138 if (r_opts->add_assoc) { 139 ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file); 140 if (ret < 0) 141 goto err; 142 143 if (ret > 0) 144 /* There was already an association and it took precedence. */ 145 goto out; 146 } 147 148 if (r_opts->debug) { 149 printf("%s: %s matched by %s\n", r_opts->progname, my_file, newcon); 150 } 151 152 /* 153 * Do not relabel if their is no default specification for this file 154 */ 155 156 if (strcmp(newcon, "<<none>>") == 0) { 157 goto out; 158 } 159 160 /* Get the current context of the file. */ 161 ret = lgetfilecon_raw(ftsent->fts_accpath, &curcon); 162 if (ret < 0) { 163 if (errno == ENODATA) { 164 curcon = NULL; 165 } else { 166 fprintf(stderr, "%s get context on %s failed: '%s'\n", 167 r_opts->progname, my_file, strerror(errno)); 168 goto err; 169 } 170 } 171 172 /* lgetfilecon returns number of characters and ret needs to be reset 173 * to 0. 174 */ 175 ret = 0; 176 177 /* 178 * Do not relabel the file if the file is already labeled according to 179 * the specification. 180 */ 181 if (curcon && (strcmp(curcon, newcon) == 0)) { 182 goto out; 183 } 184 185 if (!r_opts->force && curcon && (is_context_customizable(curcon) > 0)) { 186 if (r_opts->verbose > 1) { 187 fprintf(stderr, 188 "%s: %s not reset customized by admin to %s\n", 189 r_opts->progname, my_file, curcon); 190 } 191 goto out; 192 } 193 194 /* 195 * Do not change label unless this is a force or the type is different 196 */ 197 if (!r_opts->force && curcon) { 198 int types_differ = 0; 199 context_t cona; 200 context_t conb; 201 int err = 0; 202 cona = context_new(curcon); 203 if (! cona) { 204 goto out; 205 } 206 conb = context_new(newcon); 207 if (! conb) { 208 context_free(cona); 209 goto out; 210 } 211 212 types_differ = strcmp(context_type_get(cona), context_type_get(conb)); 213 if (types_differ) { 214 err |= context_user_set(conb, context_user_get(cona)); 215 err |= context_role_set(conb, context_role_get(cona)); 216 err |= context_range_set(conb, context_range_get(cona)); 217 if (!err) { 218 freecon(newcon); 219 newcon = strdup(context_str(conb)); 220 } 221 } 222 context_free(cona); 223 context_free(conb); 224 225 if (!types_differ || err) { 226 goto out; 227 } 228 } 229 230 if (r_opts->verbose) { 231 printf("%s reset %s context %s->%s\n", 232 r_opts->progname, my_file, curcon ?: "", newcon); 233 } 234 235 if (r_opts->logging && r_opts->change) { 236 if (curcon) 237 syslog(LOG_INFO, "relabeling %s from %s to %s\n", 238 my_file, curcon, newcon); 239 else 240 syslog(LOG_INFO, "labeling %s to %s\n", 241 my_file, newcon); 242 } 243 244 if (r_opts->outfile) 245 fprintf(r_opts->outfile, "%s\n", my_file); 246 247 /* 248 * Do not relabel the file if -n was used. 249 */ 250 if (!r_opts->change) 251 goto out; 252 253 /* 254 * Relabel the file to the specified context. 255 */ 256 ret = lsetfilecon(ftsent->fts_accpath, newcon); 257 if (ret) { 258 fprintf(stderr, "%s set context %s->%s failed:'%s'\n", 259 r_opts->progname, my_file, newcon, strerror(errno)); 260 goto skip; 261 } 262 ret = 0; 263 out: 264 freecon(curcon); 265 freecon(newcon); 266 return ret; 267 skip: 268 freecon(curcon); 269 freecon(newcon); 270 return SKIP; 271 err: 272 freecon(curcon); 273 freecon(newcon); 274 return ERR; 275 } 276 /* 277 * Apply the last matching specification to a file. 278 * This function is called by fts on each file during 279 * the directory traversal. 280 */ 281 static int apply_spec(FTSENT *ftsent, int recurse) 282 { 283 if (ftsent->fts_info == FTS_DNR) { 284 fprintf(stderr, "%s: unable to read directory %s\n", 285 r_opts->progname, ftsent->fts_path); 286 return SKIP; 287 } 288 289 int rc = restore(ftsent, recurse); 290 if (rc == ERR) { 291 if (!r_opts->abort_on_error) 292 return SKIP; 293 } 294 return rc; 295 } 296 297 #include <sys/statvfs.h> 298 299 static int process_one(char *name, int recurse_this_path) 300 { 301 int rc = 0; 302 const char *namelist[2] = {name, NULL}; 303 dev_t dev_num = 0; 304 FTS *fts_handle = NULL; 305 FTSENT *ftsent = NULL; 306 307 if (r_opts == NULL){ 308 fprintf(stderr, 309 "Must call initialize first!"); 310 goto err; 311 } 312 313 fts_handle = fts_open((char **)namelist, r_opts->fts_flags, NULL); 314 if (fts_handle == NULL) { 315 fprintf(stderr, 316 "%s: error while labeling %s: %s\n", 317 r_opts->progname, namelist[0], strerror(errno)); 318 goto err; 319 } 320 321 322 ftsent = fts_read(fts_handle); 323 if (ftsent == NULL) { 324 fprintf(stderr, 325 "%s: error while labeling %s: %s\n", 326 r_opts->progname, namelist[0], strerror(errno)); 327 goto err; 328 } 329 330 /* Keep the inode of the first one. */ 331 dev_num = ftsent->fts_statp->st_dev; 332 333 do { 334 rc = 0; 335 /* Skip the post order nodes. */ 336 if (ftsent->fts_info == FTS_DP) 337 continue; 338 /* If the XDEV flag is set and the device is different */ 339 if (ftsent->fts_statp->st_dev != dev_num && 340 FTS_XDEV == (r_opts->fts_flags & FTS_XDEV)) 341 continue; 342 if (excludeCtr > 0) { 343 if (exclude(ftsent->fts_path)) { 344 fts_set(fts_handle, ftsent, FTS_SKIP); 345 continue; 346 } 347 } 348 349 rc = apply_spec(ftsent, recurse_this_path); 350 if (rc == SKIP) 351 fts_set(fts_handle, ftsent, FTS_SKIP); 352 if (rc == ERR) 353 goto err; 354 if (!recurse_this_path) 355 break; 356 } while ((ftsent = fts_read(fts_handle)) != NULL); 357 358 out: 359 if (r_opts->add_assoc) { 360 if (!r_opts->quiet) 361 filespec_eval(); 362 filespec_destroy(); 363 } 364 if (fts_handle) 365 fts_close(fts_handle); 366 return rc; 367 368 err: 369 rc = -1; 370 goto out; 371 } 372 373 int process_glob(char *name, int recurse) { 374 glob_t globbuf; 375 size_t i = 0; 376 int errors; 377 memset(&globbuf, 0, sizeof(globbuf)); 378 errors = glob(name, GLOB_TILDE | GLOB_PERIOD | GLOB_NOCHECK, NULL, &globbuf); 379 if (errors) 380 return errors; 381 382 for (i = 0; i < globbuf.gl_pathc; i++) { 383 int len = strlen(globbuf.gl_pathv[i]) -2; 384 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) 385 continue; 386 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) 387 continue; 388 int rc = process_one_realpath(globbuf.gl_pathv[i], recurse); 389 if (rc < 0) 390 errors = rc; 391 } 392 globfree(&globbuf); 393 return errors; 394 } 395 396 int process_one_realpath(char *name, int recurse) 397 { 398 int rc = 0; 399 char *p; 400 struct stat64 sb; 401 402 if (r_opts == NULL){ 403 fprintf(stderr, 404 "Must call initialize first!"); 405 return -1; 406 } 407 408 if (!r_opts->expand_realpath) { 409 return process_one(name, recurse); 410 } else { 411 rc = lstat64(name, &sb); 412 if (rc < 0) { 413 if (r_opts->ignore_enoent && errno == ENOENT) 414 return 0; 415 fprintf(stderr, "%s: lstat(%s) failed: %s\n", 416 r_opts->progname, name, strerror(errno)); 417 return -1; 418 } 419 420 if (S_ISLNK(sb.st_mode)) { 421 char path[PATH_MAX + 1]; 422 423 rc = realpath_not_final(name, path); 424 if (rc < 0) 425 return rc; 426 rc = process_one(path, 0); 427 if (rc < 0) 428 return rc; 429 430 p = realpath(name, NULL); 431 if (p) { 432 rc = process_one(p, recurse); 433 free(p); 434 } 435 return rc; 436 } else { 437 p = realpath(name, NULL); 438 if (!p) { 439 fprintf(stderr, "realpath(%s) failed %s\n", name, 440 strerror(errno)); 441 return -1; 442 } 443 rc = process_one(p, recurse); 444 free(p); 445 return rc; 446 } 447 } 448 } 449 450 int exclude(const char *file) 451 { 452 int i = 0; 453 for (i = 0; i < excludeCtr; i++) { 454 if (strncmp 455 (file, excludeArray[i].directory, 456 excludeArray[i].size) == 0) { 457 if (file[excludeArray[i].size] == 0 458 || file[excludeArray[i].size] == '/') { 459 return 1; 460 } 461 } 462 } 463 return 0; 464 } 465 466 int add_exclude(const char *directory) 467 { 468 size_t len = 0; 469 470 if (directory == NULL || directory[0] != '/') { 471 fprintf(stderr, "Full path required for exclude: %s.\n", 472 directory); 473 return 1; 474 } 475 if (excludeCtr == MAX_EXCLUDES) { 476 fprintf(stderr, "Maximum excludes %d exceeded.\n", 477 MAX_EXCLUDES); 478 return 1; 479 } 480 481 len = strlen(directory); 482 while (len > 1 && directory[len - 1] == '/') { 483 len--; 484 } 485 excludeArray[excludeCtr].directory = strndup(directory, len); 486 487 if (excludeArray[excludeCtr].directory == NULL) { 488 fprintf(stderr, "Out of memory.\n"); 489 return 1; 490 } 491 excludeArray[excludeCtr++].size = len; 492 493 return 0; 494 } 495 496 /* 497 * Evaluate the association hash table distribution. 498 */ 499 static void filespec_eval(void) 500 { 501 file_spec_t *fl; 502 int h, used, nel, len, longest; 503 504 if (!fl_head) 505 return; 506 507 used = 0; 508 longest = 0; 509 nel = 0; 510 for (h = 0; h < HASH_BUCKETS; h++) { 511 len = 0; 512 for (fl = fl_head[h].next; fl; fl = fl->next) { 513 len++; 514 } 515 if (len) 516 used++; 517 if (len > longest) 518 longest = len; 519 nel += len; 520 } 521 522 if (r_opts->verbose > 1) 523 printf 524 ("%s: hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n", 525 __FUNCTION__, nel, used, HASH_BUCKETS, longest); 526 } 527 528 /* 529 * Destroy the association hash table. 530 */ 531 static void filespec_destroy(void) 532 { 533 file_spec_t *fl, *tmp; 534 int h; 535 536 if (!fl_head) 537 return; 538 539 for (h = 0; h < HASH_BUCKETS; h++) { 540 fl = fl_head[h].next; 541 while (fl) { 542 tmp = fl; 543 fl = fl->next; 544 freecon(tmp->con); 545 free(tmp->file); 546 free(tmp); 547 } 548 fl_head[h].next = NULL; 549 } 550 free(fl_head); 551 fl_head = NULL; 552 } 553 /* 554 * Try to add an association between an inode and a context. 555 * If there is a different context that matched the inode, 556 * then use the first context that matched. 557 */ 558 static int filespec_add(ino_t ino, const security_context_t con, const char *file) 559 { 560 file_spec_t *prevfl, *fl; 561 int h, ret; 562 struct stat64 sb; 563 564 if (!fl_head) { 565 fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS); 566 if (!fl_head) 567 goto oom; 568 memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS); 569 } 570 571 h = (ino + (ino >> HASH_BITS)) & HASH_MASK; 572 for (prevfl = &fl_head[h], fl = fl_head[h].next; fl; 573 prevfl = fl, fl = fl->next) { 574 if (ino == fl->ino) { 575 ret = lstat64(fl->file, &sb); 576 if (ret < 0 || sb.st_ino != ino) { 577 freecon(fl->con); 578 free(fl->file); 579 fl->file = strdup(file); 580 if (!fl->file) 581 goto oom; 582 fl->con = strdup(con); 583 if (!fl->con) 584 goto oom; 585 return 1; 586 } 587 588 if (strcmp(fl->con, con) == 0) 589 return 1; 590 591 fprintf(stderr, 592 "%s: conflicting specifications for %s and %s, using %s.\n", 593 __FUNCTION__, file, fl->file, fl->con); 594 free(fl->file); 595 fl->file = strdup(file); 596 if (!fl->file) 597 goto oom; 598 return 1; 599 } 600 601 if (ino > fl->ino) 602 break; 603 } 604 605 fl = malloc(sizeof(file_spec_t)); 606 if (!fl) 607 goto oom; 608 fl->ino = ino; 609 fl->con = strdup(con); 610 if (!fl->con) 611 goto oom_freefl; 612 fl->file = strdup(file); 613 if (!fl->file) 614 goto oom_freefl; 615 fl->next = prevfl->next; 616 prevfl->next = fl; 617 return 0; 618 oom_freefl: 619 free(fl); 620 oom: 621 fprintf(stderr, 622 "%s: insufficient memory for file label entry for %s\n", 623 __FUNCTION__, file); 624 return -1; 625 } 626 627 #include <sys/utsname.h> 628 int file_system_count(char *name) { 629 struct statvfs statvfs_buf; 630 int nfile = 0; 631 memset(&statvfs_buf, 0, sizeof(statvfs_buf)); 632 if (!statvfs(name, &statvfs_buf)) { 633 nfile = statvfs_buf.f_files - statvfs_buf.f_ffree; 634 } 635 return nfile; 636 } 637 638 /* 639 Search /proc/mounts for all file systems that do not support extended 640 attributes and add them to the exclude directory table. File systems 641 that support security labels have the seclabel option, return total file count 642 */ 643 int exclude_non_seclabel_mounts() 644 { 645 struct utsname uts; 646 FILE *fp; 647 size_t len; 648 ssize_t num; 649 int index = 0, found = 0; 650 char *mount_info[4]; 651 char *buf = NULL, *item; 652 int nfile = 0; 653 /* Check to see if the kernel supports seclabel */ 654 if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0) 655 return 0; 656 if (is_selinux_enabled() <= 0) 657 return 0; 658 659 fp = fopen("/proc/mounts", "r"); 660 if (!fp) 661 return 0; 662 663 while ((num = getline(&buf, &len, fp)) != -1) { 664 found = 0; 665 index = 0; 666 item = strtok(buf, " "); 667 while (item != NULL) { 668 mount_info[index] = item; 669 if (index == 3) 670 break; 671 index++; 672 item = strtok(NULL, " "); 673 } 674 if (index < 3) { 675 fprintf(stderr, 676 "/proc/mounts record \"%s\" has incorrect format.\n", 677 buf); 678 continue; 679 } 680 681 /* remove pre-existing entry */ 682 remove_exclude(mount_info[1]); 683 684 item = strtok(mount_info[3], ",");
Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

685 while (item != NULL) { 686 if (strcmp(item, "seclabel") == 0) { 687 found = 1; 688 nfile += file_system_count(mount_info[1]); 689 break; 690 } 691 item = strtok(NULL, ","); 692 } 693 694 /* exclude mount points without the seclabel option */ 695 if (!found) 696 add_exclude(mount_info[1]); 697 } 698 699 free(buf); 700 fclose(fp); 701 /* return estimated #Files + 5% for directories and hard links */ 702 return nfile * 1.05; 703 }

policycoreutils-2.1.13/setfiles/setfiles.c

No issues found

  1 #include "restore.h"
  2 #include <unistd.h>
  3 #include <fcntl.h>
  4 #include <stdio_ext.h>
  5 #include <ctype.h>
  6 #include <regex.h>
  7 #include <sys/vfs.h>
  8 #define __USE_XOPEN_EXTENDED 1	/* nftw */
  9 #include <libgen.h>
 10 #ifdef USE_AUDIT
 11 #include <libaudit.h>
 12 
 13 #ifndef AUDIT_FS_RELABEL
 14 #define AUDIT_FS_RELABEL 2309
 15 #endif
 16 #endif
 17 
 18 
 19 /* cmdline opts*/
 20 
 21 static char *policyfile = NULL;
 22 static int warn_no_match = 0;
 23 static int null_terminated = 0;
 24 static struct restore_opts r_opts;
 25 
 26 #define STAT_BLOCK_SIZE 1
 27 
 28 /* setfiles will abort its operation after reaching the
 29  * following number of errors (e.g. invalid contexts),
 30  * unless it is used in "debug" mode (-d option).
 31  */
 32 #ifndef ABORT_ON_ERRORS
 33 #define ABORT_ON_ERRORS	10
 34 #endif
 35 
 36 #define SETFILES "setfiles"
 37 #define RESTORECON "restorecon"
 38 static int iamrestorecon;
 39 
 40 /* Behavior flags determined based on setfiles vs. restorecon */
 41 static int ctx_validate; /* Validate contexts */
 42 static const char *altpath; /* Alternate path to file_contexts */
 43 
 44 void usage(const char *const name)
 45 {
 46 	if (iamrestorecon) {
 47 		fprintf(stderr,
 48 			"usage:  %s [-iFnprRv0] [-e excludedir] [-o filename] pathname...\n"
 49 			"usage:  %s [-iFnprRv0] [-e excludedir] [-o filename] -f filename\n",
 50 			name, name);
 51 	} else {
 52 		fprintf(stderr,
 53 			"usage:  %s [-dilnpqvFW] [-e excludedir] [-o filename] [-r alt_root_path] spec_file pathname...\n"
 54 			"usage:  %s [-dilnpqvFW] [-e excludedir] [-o filename] [-r alt_root_path] spec_file -f filename\n"
 55 			"usage:  %s -s [-dilnpqvFW] [-o filename] spec_file\n"
 56 			"usage:  %s -c policyfile spec_file\n",
 57 			name, name, name, name);
 58 	}
 59 	exit(1);
 60 }
 61 
 62 static int nerr = 0;
 63 
 64 void inc_err()
 65 {
 66 	nerr++;
 67 	if (nerr > ABORT_ON_ERRORS - 1 && !r_opts.debug) {
 68 		fprintf(stderr, "Exiting after %d errors.\n", ABORT_ON_ERRORS);
 69 		exit(1);
 70 	}
 71 }
 72 
 73 
 74 
 75 void set_rootpath(const char *arg)
 76 {
 77 	int len;
 78 
 79 	r_opts.rootpath = strdup(arg);
 80 	if (NULL == r_opts.rootpath) {
 81 		fprintf(stderr, "%s:  insufficient memory for r_opts.rootpath\n",
 82 			r_opts.progname);
 83 		exit(1);
 84 	}
 85 
 86 	/* trim trailing /, if present */
 87 	len = strlen(r_opts.rootpath);
 88 	while (len && ('/' == r_opts.rootpath[len - 1]))
 89 		r_opts.rootpath[--len] = 0;
 90 	r_opts.rootpathlen = len;
 91 }
 92 
 93 int canoncon(char **contextp)
 94 {
 95 	char *context = *contextp, *tmpcon;
 96 	int rc = 0;
 97 
 98 	if (policyfile) {
 99 		if (sepol_check_context(context) < 0) {
100 			fprintf(stderr, "invalid context %s\n", context);
101 			exit(1);
102 		}
103 	} else if (security_canonicalize_context_raw(context, &tmpcon) == 0) {
104 		free(context);
105 		*contextp = tmpcon;
106 	} else if (errno != ENOENT) {
107 		rc = -1;
108 		inc_err();
109 	}
110 
111 	return rc;
112 }
113 
114 #ifndef USE_AUDIT
115 static void maybe_audit_mass_relabel(int mass_relabel __attribute__((unused)),
116 				     int mass_relabel_errs __attribute__((unused)))
117 {
118 #else
119 static void maybe_audit_mass_relabel(int mass_relabel, int mass_relabel_errs)
120 {
121 	int audit_fd = -1;
122 	int rc = 0;
123 
124 	if (!mass_relabel)		/* only audit a forced full relabel */
125 		return;
126 
127 	audit_fd = audit_open();
128 
129 	if (audit_fd < 0) {
130 		fprintf(stderr, "Error connecting to audit system.\n");
131 		exit(-1);
132 	}
133 
134 	rc = audit_log_user_message(audit_fd, AUDIT_FS_RELABEL,
135 				    "op=mass relabel", NULL, NULL, NULL, !mass_relabel_errs);
136 	if (rc <= 0) {
137 		fprintf(stderr, "Error sending audit message: %s.\n",
138 			strerror(errno));
139 		/* exit(-1); -- don't exit atm. as fix for eff_cap isn't in most kernels */
140 	}
141 	audit_close(audit_fd);
142 #endif
143 }
144 
145 int main(int argc, char **argv)
146 {
147 	struct stat sb;
148 	int opt, i = 0;
149 	char *input_filename = NULL;
150 	int use_input_file = 0;
151 	char *buf = NULL;
152 	size_t buf_len;
153 	int recurse; /* Recursive descent. */
154 	char *base;
155 	int mass_relabel = 0, errors = 0;
156 	
157 	memset(&r_opts, 0, sizeof(r_opts));
158 
159 	/* Initialize variables */
160 	r_opts.progress = 0;
161 	r_opts.count = 0;
162 	r_opts.nfile = 0;
163 	r_opts.debug = 0;
164 	r_opts.change = 1;
165 	r_opts.verbose = 0;
166 	r_opts.logging = 0;
167 	r_opts.rootpath = NULL;
168 	r_opts.rootpathlen = 0;
169 	r_opts.outfile = NULL;
170 	r_opts.force = 0;
171 	r_opts.hard_links = 1;
172 
173 	altpath = NULL;
174 
175 	r_opts.progname = strdup(argv[0]);
176 	if (!r_opts.progname) {
177 		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
178 		exit(1);
179 	}
180 	base = basename(r_opts.progname);
181 	
182 	if (!strcmp(base, SETFILES)) {
183 		/* 
184 		 * setfiles:  
185 		 * Recursive descent,
186 		 * Does not expand paths via realpath, 
187 		 * Aborts on errors during the file tree walk, 
188 		 * Try to track inode associations for conflict detection,
189 		 * Does not follow mounts,
190 		 * Validates all file contexts at init time. 
191 		 */
192 		iamrestorecon = 0;
193 		recurse = 1;
194 		r_opts.expand_realpath = 0;
195 		r_opts.abort_on_error = 1;
196 		r_opts.add_assoc = 1;
197 		r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV;
198 		ctx_validate = 1;
199 	} else {
200 		/*
201 		 * restorecon:  
202 		 * No recursive descent unless -r/-R,
203 		 * Expands paths via realpath, 
204 		 * Do not abort on errors during the file tree walk,
205 		 * Do not try to track inode associations for conflict detection,
206 		 * Follows mounts,
207 		 * Does lazy validation of contexts upon use. 
208 		 */
209 		if (strcmp(base, RESTORECON) && !r_opts.quiet) 
210 			printf("Executed with an unrecognized name (%s), defaulting to %s behavior.\n", base, RESTORECON);
211 		iamrestorecon = 1;
212 		recurse = 0;
213 		r_opts.expand_realpath = 1;
214 		r_opts.abort_on_error = 0;
215 		r_opts.add_assoc = 0;
216 		r_opts.fts_flags = FTS_PHYSICAL;
217 		ctx_validate = 0;
218 
219 		/* restorecon only:  silent exit if no SELinux.
220 		   Allows unconditional execution by scripts. */
221 		if (is_selinux_enabled() <= 0)
222 			exit(0);
223 	}
224 
225 	/* This must happen before getopt. */
226 	r_opts.nfile = exclude_non_seclabel_mounts();
227 
228 	/* Process any options. */
229 	while ((opt = getopt(argc, argv, "c:de:f:hilno:pqrsvFRW0")) > 0) {
230 		switch (opt) {
231 		case 'c':
232 			{
233 				FILE *policystream;
234 
235 				if (iamrestorecon)
236 					usage(argv[0]);
237 
238 				policyfile = optarg;
239 
240 				policystream = fopen(policyfile, "r");
241 				if (!policystream) {
242 					fprintf(stderr,
243 						"Error opening %s: %s\n",
244 						policyfile, strerror(errno));
245 					exit(1);
246 				}
247 				__fsetlocking(policystream,
248 					      FSETLOCKING_BYCALLER);
249 
250 				if (sepol_set_policydb_from_file(policystream) <
251 				    0) {
252 					fprintf(stderr,
253 						"Error reading policy %s: %s\n",
254 						policyfile, strerror(errno));
255 					exit(1);
256 				}
257 				fclose(policystream);
258 
259 				ctx_validate = 1;
260 
261 				break;
262 			}
263 		case 'e':
264 			remove_exclude(optarg);
265 			if (lstat(optarg, &sb) < 0 && errno != EACCES) {
266 				fprintf(stderr, "Can't stat exclude path \"%s\", %s - ignoring.\n",
267 					optarg, strerror(errno));
268 				break;
269 			}
270 			if (add_exclude(optarg))
271 				exit(1);
272 			break;
273 		case 'f':
274 			use_input_file = 1;
275 			input_filename = optarg;
276 			break;			
277 		case 'd':
278 			if (iamrestorecon)
279 				usage(argv[0]);
280 			r_opts.debug = 1;
281 			break;
282 		case 'i':
283 			r_opts.ignore_enoent = 1;
284 			break;
285 		case 'l':
286 			r_opts.logging = 1;
287 			break;
288 		case 'F':
289 			r_opts.force = 1;
290 			break;
291 		case 'n':
292 			r_opts.change = 0;
293 			break;
294 		case 'o':
295 			if (strcmp(optarg, "-") == 0) {
296 				r_opts.outfile = stdout;
297 				break;
298 			}
299 
300 			r_opts.outfile = fopen(optarg, "w");
301 			if (!r_opts.outfile) {
302 				fprintf(stderr, "Error opening %s: %s\n",
303 					optarg, strerror(errno));
304 
305 				usage(argv[0]);
306 			}
307 			__fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER);
308 			break;
309 		case 'q':
310 			r_opts.quiet = 1;
311 			break;
312 		case 'R':
313 		case 'r':
314 			if (iamrestorecon) {
315 				recurse = 1;
316 				break;
317 			}
318 			if (optind + 1 >= argc) {
319 				fprintf(stderr, "usage:  %s -r rootpath\n",
320 					argv[0]);
321 				exit(1);
322 			}
323 			if (NULL != r_opts.rootpath) {
324 				fprintf(stderr,
325 					"%s: only one -r can be specified\n",
326 					argv[0]);
327 				exit(1);
328 			}
329 			set_rootpath(argv[optind++]);
330 			break;
331 		case 's':
332 			use_input_file = 1;
333 			input_filename = "-";
334 			r_opts.add_assoc = 0;
335 			break;
336 		case 'v':
337 			if (r_opts.progress) {
338 				fprintf(stderr,
339 					"Progress and Verbose mutually exclusive\n");
340 				exit(1);
341 			}
342 			r_opts.verbose++;
343 			break;
344 		case 'p':
345 			if (r_opts.verbose) {
346 				fprintf(stderr,
347 					"Progress and Verbose mutually exclusive\n");
348 				usage(argv[0]);
349 			}
350 			r_opts.progress++;
351 			break;
352 		case 'W':
353 			warn_no_match = 1;
354 			break;
355 		case '0':
356 			null_terminated = 1;
357 			break;
358 		case 'h':
359 		case '?':
360 			usage(argv[0]);
361 		}
362 	}
363 
364 	for (i = optind; i < argc; i++) {
365 		if (!strcmp(argv[i], "/")) {
366 			mass_relabel = 1;
367 			if (r_opts.progress)
368 				r_opts.progress++;
369 		}
370 	}
371 
372 	if (!iamrestorecon) {
373 		if (policyfile) {
374 			if (optind != (argc - 1))
375 				usage(argv[0]);
376 		} else if (use_input_file) {
377 			if (optind != (argc - 1)) {
378 				/* Cannot mix with pathname arguments. */
379 				usage(argv[0]);
380 			}
381 		} else {
382 			if (optind > (argc - 2))
383 				usage(argv[0]);
384 		}
385 
386 		/* Use our own invalid context checking function so that
387 		   we can support either checking against the active policy or
388 		   checking against a binary policy file. */
389 		selinux_set_callback(SELINUX_CB_VALIDATE,
390 				     (union selinux_callback)&canoncon);
391 
392 		if (stat(argv[optind], &sb) < 0) {
393 			perror(argv[optind]);
394 			exit(1);
395 		}
396 		if (!S_ISREG(sb.st_mode)) {
397 			fprintf(stderr, "%s:  spec file %s is not a regular file.\n",
398 				argv[0], argv[optind]);
399 			exit(1);
400 		}
401 
402 		altpath = argv[optind];
403 		optind++;
404 	} else if (argc == 1)
405 		usage(argv[0]);
406 
407 	/* Load the file contexts configuration and check it. */
408 	r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL);
409 	r_opts.selabel_opt_path = altpath;
410 
411 	if (nerr)
412 		exit(1);
413 
414 	restore_init(&r_opts);
415 	if (use_input_file) {
416 		FILE *f = stdin;
417 		ssize_t len;
418 		int delim;
419 		if (strcmp(input_filename, "-") != 0)
420 			f = fopen(input_filename, "r");
421 		if (f == NULL) {
422 			fprintf(stderr, "Unable to open %s: %s\n", input_filename,
423 				strerror(errno));
424 			usage(argv[0]);
425 		}
426 		__fsetlocking(f, FSETLOCKING_BYCALLER);
427 
428 		delim = (null_terminated != 0) ? '\0' : '\n';
429 		while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) {
430 			buf[len - 1] = 0;
431 			if (!strcmp(buf, "/"))
432 				mass_relabel = 1;
433 			errors |= process_glob(buf, recurse) < 0;
434 		}
435 		if (strcmp(input_filename, "-") != 0)
436 			fclose(f);
437 	} else {
438 		for (i = optind; i < argc; i++)
439 			errors |= process_glob(argv[i], recurse) < 0;
440 	}
441 	
442 	maybe_audit_mass_relabel(mass_relabel, errors);
443 
444 	if (warn_no_match)
445 		selabel_stats(r_opts.hnd);
446 
447 	selabel_close(r_opts.hnd);
448 	restore_finish();
449 
450 	if (r_opts.outfile)
451 		fclose(r_opts.outfile);
452 
453 	if (r_opts.progress && r_opts.count >= STAR_COUNT)
454 		printf("\n");
455 	exit(errors);
456 }

policycoreutils-2.1.13/setsebool/setsebool.c

No issues found

  1 #include <unistd.h>
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <sys/stat.h>
  6 #include <fcntl.h>
  7 #include <errno.h>
  8 #include <syslog.h>
  9 #include <getopt.h>
 10 #include <pwd.h>
 11 #include <selinux/selinux.h>
 12 #include <semanage/handle.h>
 13 #include <semanage/booleans_local.h>
 14 #include <semanage/booleans_active.h>
 15 #include <semanage/boolean_record.h>
 16 #include <errno.h>
 17 
 18 int permanent = 0;
 19 int reload = 1;
 20 
 21 int setbool(char **list, size_t start, size_t end);
 22 
 23 void usage(void)
 24 {
 25 	fputs
 26 	    ("\nUsage:  setsebool [ -NP ] boolean value | bool1=val1 bool2=val2...\n\n",
 27 	     stderr);
 28 	exit(1);
 29 }
 30 
 31 int main(int argc, char **argv)
 32 {
 33 	size_t rc;
 34 	int clflag;		/* holds codes for command line flags */
 35 	if (argc < 2)
 36 		usage();
 37 
 38 	if (is_selinux_enabled() <= 0) {
 39 		fputs("setsebool:  SELinux is disabled.\n", stderr);
 40 		return 1;
 41 	}
 42 
 43 	while (1) {
 44 		clflag = getopt(argc, argv, "PN");
 45 		if (clflag == -1)
 46 			break;
 47 
 48 		switch (clflag) {
 49 		case 'P':
 50 			permanent = 1;
 51 			break;
 52 		case 'N':
 53 		        reload = 0;
 54 			break;
 55 		default:
 56 			usage();
 57 			break;
 58 		}
 59 	}
 60 
 61 	if (argc - optind < 1) {
 62 		fprintf(stderr, "Error: boolean name required\n");
 63 		usage();
 64 	}
 65 
 66 	/* Check to see which way we are being called. If a '=' is passed,
 67 	   we'll enforce the list syntax. If not we'll enforce the original
 68 	   syntax for backward compatibility. */
 69 	if (strchr(argv[optind], '=') == 0) {
 70 		int len;
 71 		char *bool_list[1];
 72 
 73 		if ((argc - optind) != 2)
 74 			usage();
 75 
 76 		/* Add 1 for the '=' */
 77 		len = strlen(argv[optind]) + strlen(argv[optind + 1]) + 2;
 78 		bool_list[0] = (char *)malloc(len);
 79 		if (bool_list[0] == 0) {
 80 			fputs("Out of memory - aborting\n", stderr);
 81 			return 1;
 82 		}
 83 		snprintf(bool_list[0], len, "%s=%s", argv[optind],
 84 			 argv[optind + 1]);
 85 		rc = setbool(bool_list, 0, 1);
 86 		free(bool_list[0]);
 87 	} else
 88 		rc = setbool(argv, optind, argc);
 89 
 90 	return rc;
 91 }
 92 
 93 /* Apply temporal boolean changes to policy via libselinux */
 94 static int selinux_set_boolean_list(size_t boolcnt,
 95 				    SELboolean * boollist)
 96 {
 97 
 98 	if (security_set_boolean_list(boolcnt, boollist, 0)) {
 99 		if (errno == ENOENT)
100 			fprintf(stderr, "Could not change active booleans: "
101 				"Invalid boolean\n");
102 		else if (errno) {
103 			if (getuid() == 0) {
104 				perror("Could not change active booleans");
105 			} else {
106 				perror("Could not change active booleans. Please try as root");
107 			}
108 		}
109 
110 		return -1;
111 	}
112 
113 	return 0;
114 }
115 
116 /* Apply permanent boolean changes to policy via libsemanage */
117 static int semanage_set_boolean_list(size_t boolcnt,
118 				     SELboolean * boollist)
119 {
120 
121 	size_t j;
122 	semanage_handle_t *handle = NULL;
123 	semanage_bool_t *boolean = NULL;
124 	semanage_bool_key_t *bool_key = NULL;
125 	int managed;
126 
127 	handle = semanage_handle_create();
128 	if (handle == NULL) {
129 		fprintf(stderr, "Could not create semanage library handle\n");
130 		goto err;
131 	}
132 
133 	managed = semanage_is_managed(handle);
134 	if (managed < 0) {
135 		fprintf(stderr,
136 			"Error when checking whether policy is managed\n");
137 		goto err;
138 
139 	} else if (managed == 0) {
140 		if (getuid() == 0) {
141 			fprintf(stderr,
142 				"Cannot set persistent booleans without managed policy.\n");
143 		} else {
144 			fprintf(stderr,
145 				"Cannot set persistent booleans, please try as root.\n");
146 		}
147 		goto err;
148 	}
149 
150 	if (semanage_connect(handle) < 0)
151 		goto err;
152 
153 	if (semanage_begin_transaction(handle) < 0)
154 		goto err;
155 
156 	for (j = 0; j < boolcnt; j++) {
157 
158 		if (semanage_bool_create(handle, &boolean) < 0)
159 			goto err;
160 
161 		if (semanage_bool_set_name(handle, boolean, boollist[j].name) <
162 		    0)
163 			goto err;
164 
165 		semanage_bool_set_value(boolean, boollist[j].value);
166 
167 		if (semanage_bool_key_extract(handle, boolean, &bool_key) < 0)
168 			goto err;
169 
170 		if (semanage_bool_modify_local(handle, bool_key,
171 						  boolean) < 0)
172 			goto err;
173 
174 		if (semanage_bool_set_active(handle, bool_key, boolean) < 0) {
175 			fprintf(stderr, "Could not change boolean %s\n",
176 				boollist[j].name);
177 			goto err;
178 		}
179 		semanage_bool_key_free(bool_key);
180 		semanage_bool_free(boolean);
181 		bool_key = NULL;
182 		boolean = NULL;
183 	}
184 
185 	semanage_set_reload(handle, reload);
186 	if (semanage_commit(handle) < 0)
187 		goto err;
188 
189 	semanage_disconnect(handle);
190 	semanage_handle_destroy(handle);
191 	return 0;
192 
193       err:
194 	semanage_bool_key_free(bool_key);
195 	semanage_bool_free(boolean);
196 	semanage_handle_destroy(handle);
197 	fprintf(stderr, "Could not change policy booleans\n");
198 	return -1;
199 }
200 
201 /* Given an array of strings in the form "boolname=value", a start index,
202    and a finish index...walk the list and set the bool. */
203 int setbool(char **list, size_t start, size_t end)
204 {
205 	char *name, *value_ptr;
206 	int j = 0, value;
207 	size_t i = start;
208 	size_t boolcnt = end - start;
209 	struct passwd *pwd;
210 	SELboolean *vallist = calloc(boolcnt, sizeof(SELboolean));
211 	if (!vallist)
212 		goto omem;
213 
214 	while (i < end) {
215 		name = list[i];
216 		value_ptr = strchr(list[i], '=');
217 		if (value_ptr == 0) {
218 			fprintf(stderr,
219 				"setsebool: '=' not found in boolean expression %s\n",
220 				list[i]);
221 			goto err;
222 		}
223 		*value_ptr = 0;
224 		value_ptr++;
225 		if (strcmp(value_ptr, "1") == 0 ||
226 		    strcasecmp(value_ptr, "true") == 0 ||
227 		    strcasecmp(value_ptr, "on") == 0)
228 			value = 1;
229 		else if (strcmp(value_ptr, "0") == 0 ||
230 			 strcasecmp(value_ptr, "false") == 0 ||
231 			 strcasecmp(value_ptr, "off") == 0)
232 			value = 0;
233 		else {
234 			fprintf(stderr, "setsebool: illegal value "
235 				"%s for boolean %s\n", value_ptr, name);
236 			goto err;
237 		}
238 
239 		vallist[j].value = value;
240 		vallist[j].name = strdup(name);
241 		if (!vallist[j].name)
242 			goto omem;
243 		i++;
244 		j++;
245 
246 		/* Now put it back */
247 		value_ptr--;
248 		*value_ptr = '=';
249 	}
250 
251 	if (permanent) {
252 		if (semanage_set_boolean_list(boolcnt, vallist) < 0)
253 			goto err;
254 	} else {
255 		if (selinux_set_boolean_list(boolcnt, vallist) < 0)
256 			goto err;
257 	}
258 
259 	/* Now log what was done */
260 	pwd = getpwuid(getuid());
261 	i = start;
262 	while (i < end) {
263 		name = list[i];
264 		value_ptr = strchr(name, '=');
265 		*value_ptr = 0;
266 		value_ptr++;
267 		if (pwd && pwd->pw_name)
268 			syslog(LOG_NOTICE,
269 			       "The %s policy boolean was changed to %s by %s",
270 			       name, value_ptr, pwd->pw_name);
271 		else
272 			syslog(LOG_NOTICE,
273 			       "The %s policy boolean was changed to %s by uid:%d",
274 			       name, value_ptr, getuid());
275 		i++;
276 	}
277 
278 	for (i = 0; i < boolcnt; i++)
279 		free(vallist[i].name);
280 	free(vallist);
281 	return 0;
282 
283       omem:
284 	fprintf(stderr, "setsebool: out of memory");
285 
286       err:
287 	if (vallist) {
288 		for (i = 0; i < boolcnt; i++)
289 			free(vallist[i].name);
290 		free(vallist);
291 	}
292 	return -1;
293 }