Blame view

security/tomoyo/domain.c 14.6 KB
26a2a1c9e   Kentaro Takeda   Domain transition...
1
2
3
  /*
   * security/tomoyo/domain.c
   *
c3ef1500e   Tetsuo Handa   TOMOYO: Split fil...
4
   * Domain transition functions for TOMOYO.
26a2a1c9e   Kentaro Takeda   Domain transition...
5
   *
c3ef1500e   Tetsuo Handa   TOMOYO: Split fil...
6
   * Copyright (C) 2005-2010  NTT DATA CORPORATION
26a2a1c9e   Kentaro Takeda   Domain transition...
7
8
9
   */
  
  #include "common.h"
26a2a1c9e   Kentaro Takeda   Domain transition...
10
  #include <linux/binfmts.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
26a2a1c9e   Kentaro Takeda   Domain transition...
12
13
14
15
16
  
  /* Variables definitions.*/
  
  /* The initial domain. */
  struct tomoyo_domain_info tomoyo_kernel_domain;
237ab459f   Tetsuo Handa   TOMOYO: Use callb...
17
  /**
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
   * tomoyo_update_policy - Update an entry for exception policy.
   *
   * @new_entry:       Pointer to "struct tomoyo_acl_info".
   * @size:            Size of @new_entry in bytes.
   * @is_delete:       True if it is a delete request.
   * @list:            Pointer to "struct list_head".
   * @check_duplicate: Callback function to find duplicated entry.
   *
   * Returns 0 on success, negative value otherwise.
   *
   * Caller holds tomoyo_read_lock().
   */
  int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
  			 bool is_delete, struct list_head *list,
  			 bool (*check_duplicate) (const struct tomoyo_acl_head
  						  *,
  						  const struct tomoyo_acl_head
  						  *))
  {
  	int error = is_delete ? -ENOENT : -ENOMEM;
  	struct tomoyo_acl_head *entry;
  
  	if (mutex_lock_interruptible(&tomoyo_policy_lock))
  		return -ENOMEM;
  	list_for_each_entry_rcu(entry, list, list) {
  		if (!check_duplicate(entry, new_entry))
  			continue;
  		entry->is_deleted = is_delete;
  		error = 0;
  		break;
  	}
  	if (error && !is_delete) {
  		entry = tomoyo_commit_ok(new_entry, size);
  		if (entry) {
  			list_add_tail_rcu(&entry->list, list);
  			error = 0;
  		}
  	}
  	mutex_unlock(&tomoyo_policy_lock);
  	return error;
  }
  
  /**
237ab459f   Tetsuo Handa   TOMOYO: Use callb...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
   * tomoyo_update_domain - Update an entry for domain policy.
   *
   * @new_entry:       Pointer to "struct tomoyo_acl_info".
   * @size:            Size of @new_entry in bytes.
   * @is_delete:       True if it is a delete request.
   * @domain:          Pointer to "struct tomoyo_domain_info".
   * @check_duplicate: Callback function to find duplicated entry.
   * @merge_duplicate: Callback function to merge duplicated entry.
   *
   * Returns 0 on success, negative value otherwise.
   *
   * Caller holds tomoyo_read_lock().
   */
  int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
  			 bool is_delete, struct tomoyo_domain_info *domain,
  			 bool (*check_duplicate) (const struct tomoyo_acl_info
  						  *,
  						  const struct tomoyo_acl_info
  						  *),
  			 bool (*merge_duplicate) (struct tomoyo_acl_info *,
  						  struct tomoyo_acl_info *,
  						  const bool))
  {
  	int error = is_delete ? -ENOENT : -ENOMEM;
  	struct tomoyo_acl_info *entry;
  
  	if (mutex_lock_interruptible(&tomoyo_policy_lock))
  		return error;
  	list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
  		if (!check_duplicate(entry, new_entry))
  			continue;
  		if (merge_duplicate)
  			entry->is_deleted = merge_duplicate(entry, new_entry,
  							    is_delete);
  		else
  			entry->is_deleted = is_delete;
  		error = 0;
  		break;
  	}
  	if (error && !is_delete) {
  		entry = tomoyo_commit_ok(new_entry, size);
  		if (entry) {
  			list_add_tail_rcu(&entry->list, &domain->acl_info_list);
  			error = 0;
  		}
  	}
  	mutex_unlock(&tomoyo_policy_lock);
  	return error;
  }
99a852596   Tetsuo Handa   TOMOYO: Use callb...
110
  void tomoyo_check_acl(struct tomoyo_request_info *r,
484ca79c6   Tetsuo Handa   TOMOYO: Use pathn...
111
  		      bool (*check_entry) (struct tomoyo_request_info *,
99a852596   Tetsuo Handa   TOMOYO: Use callb...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  					   const struct tomoyo_acl_info *))
  {
  	const struct tomoyo_domain_info *domain = r->domain;
  	struct tomoyo_acl_info *ptr;
  
  	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  		if (ptr->is_deleted || ptr->type != r->param_type)
  			continue;
  		if (check_entry(r, ptr)) {
  			r->granted = true;
  			return;
  		}
  	}
  	r->granted = false;
  }
a230f9e71   Tetsuo Handa   TOMOYO: Use array...
127
  /* The list for "struct tomoyo_domain_info". */
26a2a1c9e   Kentaro Takeda   Domain transition...
128
  LIST_HEAD(tomoyo_domain_list);
26a2a1c9e   Kentaro Takeda   Domain transition...
129

a230f9e71   Tetsuo Handa   TOMOYO: Use array...
130
131
  struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
  struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
26a2a1c9e   Kentaro Takeda   Domain transition...
132
  /**
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
133
   * tomoyo_last_word - Get last component of a domainname.
26a2a1c9e   Kentaro Takeda   Domain transition...
134
   *
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
135
   * @domainname: Domainname to check.
26a2a1c9e   Kentaro Takeda   Domain transition...
136
   *
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
137
   * Returns the last word of @domainname.
26a2a1c9e   Kentaro Takeda   Domain transition...
138
   */
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
139
  static const char *tomoyo_last_word(const char *name)
26a2a1c9e   Kentaro Takeda   Domain transition...
140
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
141
142
143
144
          const char *cp = strrchr(name, ' ');
          if (cp)
                  return cp + 1;
          return name;
26a2a1c9e   Kentaro Takeda   Domain transition...
145
  }
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
146
147
  static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
  					   const struct tomoyo_acl_head *b)
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
148
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
149
150
151
152
153
154
155
  	const struct tomoyo_transition_control *p1 = container_of(a,
  								  typeof(*p1),
  								  head);
  	const struct tomoyo_transition_control *p2 = container_of(b,
  								  typeof(*p2),
  								  head);
  	return p1->type == p2->type && p1->is_last_name == p2->is_last_name
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
156
157
158
  		&& p1->domainname == p2->domainname
  		&& p1->program == p2->program;
  }
26a2a1c9e   Kentaro Takeda   Domain transition...
159
  /**
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
160
   * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
26a2a1c9e   Kentaro Takeda   Domain transition...
161
   *
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
162
163
164
   * @domainname: The name of domain. Maybe NULL.
   * @program:    The name of program. Maybe NULL.
   * @type:       Type of transition.
26a2a1c9e   Kentaro Takeda   Domain transition...
165
166
167
168
   * @is_delete:  True if it is a delete request.
   *
   * Returns 0 on success, negative value otherwise.
   */
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
169
  static int tomoyo_update_transition_control_entry(const char *domainname,
26a2a1c9e   Kentaro Takeda   Domain transition...
170
  						  const char *program,
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
171
  						  const u8 type,
26a2a1c9e   Kentaro Takeda   Domain transition...
172
173
  						  const bool is_delete)
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
174
  	struct tomoyo_transition_control e = { .type = type };
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
175
  	int error = is_delete ? -ENOENT : -ENOMEM;
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
176
177
178
179
180
181
182
  	if (program) {
  		if (!tomoyo_correct_path(program))
  			return -EINVAL;
  		e.program = tomoyo_get_name(program);
  		if (!e.program)
  			goto out;
  	}
26a2a1c9e   Kentaro Takeda   Domain transition...
183
  	if (domainname) {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
184
185
186
  		if (!tomoyo_correct_domain(domainname)) {
  			if (!tomoyo_correct_path(domainname))
  				goto out;
9e4b50e93   Tetsuo Handa   TOMOYO: Use stack...
187
  			e.is_last_name = true;
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
188
  		}
9e4b50e93   Tetsuo Handa   TOMOYO: Use stack...
189
190
  		e.domainname = tomoyo_get_name(domainname);
  		if (!e.domainname)
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
191
  			goto out;
26a2a1c9e   Kentaro Takeda   Domain transition...
192
  	}
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
193
  	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
a230f9e71   Tetsuo Handa   TOMOYO: Use array...
194
  				     &tomoyo_policy_list
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
195
  				     [TOMOYO_ID_TRANSITION_CONTROL],
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
196
  				     tomoyo_same_transition_control);
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
197
   out:
9e4b50e93   Tetsuo Handa   TOMOYO: Use stack...
198
199
  	tomoyo_put_name(e.domainname);
  	tomoyo_put_name(e.program);
26a2a1c9e   Kentaro Takeda   Domain transition...
200
201
202
203
  	return error;
  }
  
  /**
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
204
   * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
26a2a1c9e   Kentaro Takeda   Domain transition...
205
206
   *
   * @data:      String to parse.
26a2a1c9e   Kentaro Takeda   Domain transition...
207
   * @is_delete: True if it is a delete request.
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
208
   * @type:      Type of this entry.
26a2a1c9e   Kentaro Takeda   Domain transition...
209
210
211
   *
   * Returns 0 on success, negative value otherwise.
   */
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
212
213
  int tomoyo_write_transition_control(char *data, const bool is_delete,
  				    const u8 type)
26a2a1c9e   Kentaro Takeda   Domain transition...
214
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
215
216
217
218
219
220
221
222
  	char *domainname = strstr(data, " from ");
  	if (domainname) {
  		*domainname = '\0';
  		domainname += 6;
  	} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
  		   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
  		domainname = data;
  		data = NULL;
26a2a1c9e   Kentaro Takeda   Domain transition...
223
  	}
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
224
  	return tomoyo_update_transition_control_entry(domainname, data, type,
26a2a1c9e   Kentaro Takeda   Domain transition...
225
226
227
228
  						      is_delete);
  }
  
  /**
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
229
   * tomoyo_transition_type - Get domain transition type.
26a2a1c9e   Kentaro Takeda   Domain transition...
230
231
232
   *
   * @domainname: The name of domain.
   * @program:    The name of program.
26a2a1c9e   Kentaro Takeda   Domain transition...
233
   *
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
234
235
236
   * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
   * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
   * @program suppresses domain transition, others otherwise.
fdb8ebb72   Tetsuo Handa   TOMOYO: Use RCU p...
237
238
   *
   * Caller holds tomoyo_read_lock().
26a2a1c9e   Kentaro Takeda   Domain transition...
239
   */
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
240
241
  static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
  				 const struct tomoyo_path_info *program)
26a2a1c9e   Kentaro Takeda   Domain transition...
242
  {
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
243
244
245
246
247
248
249
250
251
  	const struct tomoyo_transition_control *ptr;
  	const char *last_name = tomoyo_last_word(domainname->name);
  	u8 type;
  	for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
   next:
  		list_for_each_entry_rcu(ptr, &tomoyo_policy_list
  					[TOMOYO_ID_TRANSITION_CONTROL],
  					head.list) {
  			if (ptr->head.is_deleted || ptr->type != type)
26a2a1c9e   Kentaro Takeda   Domain transition...
252
  				continue;
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  			if (ptr->domainname) {
  				if (!ptr->is_last_name) {
  					if (ptr->domainname != domainname)
  						continue;
  				} else {
  					/*
  					 * Use direct strcmp() since this is
  					 * unlikely used.
  					 */
  					if (strcmp(ptr->domainname->name,
  						   last_name))
  						continue;
  				}
  			}
  			if (ptr->program &&
  			    tomoyo_pathcmp(ptr->program, program))
26a2a1c9e   Kentaro Takeda   Domain transition...
269
  				continue;
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
270
271
272
273
274
275
276
277
278
  			if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
  				/*
  				 * Do not check for initialize_domain if
  				 * no_initialize_domain matched.
  				 */
  				type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
  				goto next;
  			}
  			goto done;
26a2a1c9e   Kentaro Takeda   Domain transition...
279
  		}
26a2a1c9e   Kentaro Takeda   Domain transition...
280
  	}
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
281
282
   done:
  	return type;
26a2a1c9e   Kentaro Takeda   Domain transition...
283
  }
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
284
285
  static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
  				   const struct tomoyo_acl_head *b)
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
286
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
287
288
  	const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head);
  	const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head);
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
289
290
291
  	return p1->original_name == p2->original_name &&
  		p1->aggregated_name == p2->aggregated_name;
  }
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
292
  /**
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
293
   * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list.
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
294
295
296
297
298
299
300
301
302
303
304
305
306
   *
   * @original_name:   The original program's name.
   * @aggregated_name: The program name to use.
   * @is_delete:       True if it is a delete request.
   *
   * Returns 0 on success, negative value otherwise.
   *
   * Caller holds tomoyo_read_lock().
   */
  static int tomoyo_update_aggregator_entry(const char *original_name,
  					  const char *aggregated_name,
  					  const bool is_delete)
  {
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
307
  	struct tomoyo_aggregator e = { };
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
308
  	int error = is_delete ? -ENOENT : -ENOMEM;
75093152a   Tetsuo Handa   TOMOYO: Rename sy...
309
310
  	if (!tomoyo_correct_path(original_name) ||
  	    !tomoyo_correct_path(aggregated_name))
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
311
312
313
314
315
316
  		return -EINVAL;
  	e.original_name = tomoyo_get_name(original_name);
  	e.aggregated_name = tomoyo_get_name(aggregated_name);
  	if (!e.original_name || !e.aggregated_name ||
  	    e.aggregated_name->is_patterned) /* No patterns allowed. */
  		goto out;
36f5e1ffb   Tetsuo Handa   TOMOYO: Use callb...
317
  	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
a230f9e71   Tetsuo Handa   TOMOYO: Use array...
318
  				     &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
319
  				     tomoyo_same_aggregator);
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
320
321
322
323
324
325
326
   out:
  	tomoyo_put_name(e.original_name);
  	tomoyo_put_name(e.aggregated_name);
  	return error;
  }
  
  /**
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
327
   * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
328
329
330
331
332
333
334
335
   *
   * @data:      String to parse.
   * @is_delete: True if it is a delete request.
   *
   * Returns 0 on success, negative value otherwise.
   *
   * Caller holds tomoyo_read_lock().
   */
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
336
  int tomoyo_write_aggregator(char *data, const bool is_delete)
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
337
338
339
340
341
342
343
344
  {
  	char *cp = strchr(data, ' ');
  
  	if (!cp)
  		return -EINVAL;
  	*cp++ = '\0';
  	return tomoyo_update_aggregator_entry(data, cp, is_delete);
  }
26a2a1c9e   Kentaro Takeda   Domain transition...
345
  /**
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
346
   * tomoyo_assign_domain - Create a domain.
26a2a1c9e   Kentaro Takeda   Domain transition...
347
348
349
350
351
   *
   * @domainname: The name of domain.
   * @profile:    Profile number to assign if the domain was newly created.
   *
   * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
fdb8ebb72   Tetsuo Handa   TOMOYO: Use RCU p...
352
353
   *
   * Caller holds tomoyo_read_lock().
26a2a1c9e   Kentaro Takeda   Domain transition...
354
   */
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
355
356
  struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
  						const u8 profile)
26a2a1c9e   Kentaro Takeda   Domain transition...
357
  {
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
358
  	struct tomoyo_domain_info *entry;
292823814   Tetsuo Handa   TOMOYO: Use mutex...
359
  	struct tomoyo_domain_info *domain = NULL;
26a2a1c9e   Kentaro Takeda   Domain transition...
360
  	const struct tomoyo_path_info *saved_domainname;
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
361
  	bool found = false;
26a2a1c9e   Kentaro Takeda   Domain transition...
362

75093152a   Tetsuo Handa   TOMOYO: Rename sy...
363
  	if (!tomoyo_correct_domain(domainname))
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
364
  		return NULL;
bf24fb016   Tetsuo Handa   TOMOYO: Add refco...
365
  	saved_domainname = tomoyo_get_name(domainname);
26a2a1c9e   Kentaro Takeda   Domain transition...
366
  	if (!saved_domainname)
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
367
  		return NULL;
4e5d6f7ec   Tetsuo Handa   TOMOYO: Use GFP_N...
368
  	entry = kzalloc(sizeof(*entry), GFP_NOFS);
292823814   Tetsuo Handa   TOMOYO: Use mutex...
369
370
  	if (mutex_lock_interruptible(&tomoyo_policy_lock))
  		goto out;
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
371
372
373
374
375
376
377
378
379
380
  	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  		if (domain->is_deleted ||
  		    tomoyo_pathcmp(saved_domainname, domain->domainname))
  			continue;
  		found = true;
  		break;
  	}
  	if (!found && tomoyo_memory_ok(entry)) {
  		INIT_LIST_HEAD(&entry->acl_info_list);
  		entry->domainname = saved_domainname;
bf24fb016   Tetsuo Handa   TOMOYO: Add refco...
381
  		saved_domainname = NULL;
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
382
383
384
385
386
  		entry->profile = profile;
  		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
  		domain = entry;
  		entry = NULL;
  		found = true;
26a2a1c9e   Kentaro Takeda   Domain transition...
387
  	}
f737d95dd   Tetsuo Handa   TOMOYO: Replace r...
388
  	mutex_unlock(&tomoyo_policy_lock);
292823814   Tetsuo Handa   TOMOYO: Use mutex...
389
   out:
bf24fb016   Tetsuo Handa   TOMOYO: Add refco...
390
  	tomoyo_put_name(saved_domainname);
ca0b7df33   Tetsuo Handa   TOMOYO: Reduce li...
391
392
  	kfree(entry);
  	return found ? domain : NULL;
26a2a1c9e   Kentaro Takeda   Domain transition...
393
394
395
396
397
  }
  
  /**
   * tomoyo_find_next_domain - Find a domain.
   *
56f8c9bc4   Tetsuo Handa   TOMOYO: Remove ne...
398
   * @bprm: Pointer to "struct linux_binprm".
26a2a1c9e   Kentaro Takeda   Domain transition...
399
400
   *
   * Returns 0 on success, negative value otherwise.
fdb8ebb72   Tetsuo Handa   TOMOYO: Use RCU p...
401
402
   *
   * Caller holds tomoyo_read_lock().
26a2a1c9e   Kentaro Takeda   Domain transition...
403
   */
56f8c9bc4   Tetsuo Handa   TOMOYO: Remove ne...
404
  int tomoyo_find_next_domain(struct linux_binprm *bprm)
26a2a1c9e   Kentaro Takeda   Domain transition...
405
  {
17fcfbd9d   Tetsuo Handa   TOMOYO: Add inter...
406
  	struct tomoyo_request_info r;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
407
  	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
26a2a1c9e   Kentaro Takeda   Domain transition...
408
409
  	struct tomoyo_domain_info *old_domain = tomoyo_domain();
  	struct tomoyo_domain_info *domain = NULL;
26a2a1c9e   Kentaro Takeda   Domain transition...
410
  	const char *original_name = bprm->filename;
57c2590fb   Tetsuo Handa   TOMOYO: Update pr...
411
412
  	u8 mode;
  	bool is_enforce;
26a2a1c9e   Kentaro Takeda   Domain transition...
413
  	int retval = -ENOMEM;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
414
415
  	bool need_kfree = false;
  	struct tomoyo_path_info rn = { }; /* real name */
26a2a1c9e   Kentaro Takeda   Domain transition...
416

57c2590fb   Tetsuo Handa   TOMOYO: Update pr...
417
418
  	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
  	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
26a2a1c9e   Kentaro Takeda   Domain transition...
419
420
  	if (!tmp)
  		goto out;
17fcfbd9d   Tetsuo Handa   TOMOYO: Add inter...
421
   retry:
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
422
423
424
425
  	if (need_kfree) {
  		kfree(rn.name);
  		need_kfree = false;
  	}
0617c7ff3   Tetsuo Handa   TOMOYO: Remove al...
426
  	/* Get symlink's pathname of program. */
26a2a1c9e   Kentaro Takeda   Domain transition...
427
  	retval = -ENOENT;
0617c7ff3   Tetsuo Handa   TOMOYO: Remove al...
428
  	rn.name = tomoyo_realpath_nofollow(original_name);
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
429
  	if (!rn.name)
26a2a1c9e   Kentaro Takeda   Domain transition...
430
  		goto out;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
431
432
  	tomoyo_fill_path_info(&rn);
  	need_kfree = true;
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
433
434
  	/* Check 'aggregator' directive. */
  	{
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
435
  		struct tomoyo_aggregator *ptr;
a230f9e71   Tetsuo Handa   TOMOYO: Use array...
436
437
  		list_for_each_entry_rcu(ptr, &tomoyo_policy_list
  					[TOMOYO_ID_AGGREGATOR], head.list) {
82e0f001a   Tetsuo Handa   TOMOYO: Use commo...
438
  			if (ptr->head.is_deleted ||
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
439
440
441
  			    !tomoyo_path_matches_pattern(&rn,
  							 ptr->original_name))
  				continue;
0617c7ff3   Tetsuo Handa   TOMOYO: Remove al...
442
  			kfree(rn.name);
1084307ca   Tetsuo Handa   TOMOYO: Add pathn...
443
444
445
446
447
448
  			need_kfree = false;
  			/* This is OK because it is read only. */
  			rn = *ptr->aggregated_name;
  			break;
  		}
  	}
26a2a1c9e   Kentaro Takeda   Domain transition...
449
  	/* Check execute permission. */
05336dee9   Tetsuo Handa   TOMOYO: Use commo...
450
  	retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
17fcfbd9d   Tetsuo Handa   TOMOYO: Add inter...
451
452
  	if (retval == TOMOYO_RETRY_REQUEST)
  		goto retry;
26a2a1c9e   Kentaro Takeda   Domain transition...
453
454
  	if (retval < 0)
  		goto out;
484ca79c6   Tetsuo Handa   TOMOYO: Use pathn...
455
456
457
458
459
460
461
462
463
464
465
466
467
  	/*
  	 * To be able to specify domainnames with wildcards, use the
  	 * pathname specified in the policy (which may contain
  	 * wildcard) rather than the pathname passed to execve()
  	 * (which never contains wildcard).
  	 */
  	if (r.param.path.matched_path) {
  		if (need_kfree)
  			kfree(rn.name);
  		need_kfree = false;
  		/* This is OK because it is read only. */
  		rn = *r.param.path.matched_path;
  	}
26a2a1c9e   Kentaro Takeda   Domain transition...
468

5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
469
470
471
  	/* Calculate domain to transit to. */
  	switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
  	case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
26a2a1c9e   Kentaro Takeda   Domain transition...
472
  		/* Transit to the child of tomoyo_kernel_domain domain. */
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
473
474
475
476
  		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
  			 "%s", rn.name);
  		break;
  	case TOMOYO_TRANSITION_CONTROL_KEEP:
26a2a1c9e   Kentaro Takeda   Domain transition...
477
478
  		/* Keep current domain. */
  		domain = old_domain;
5448ec4f5   Tetsuo Handa   TOMOYO: Use commo...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  		break;
  	default:
  		if (old_domain == &tomoyo_kernel_domain &&
  		    !tomoyo_policy_loaded) {
  			/*
  			 * Needn't to transit from kernel domain before
  			 * starting /sbin/init. But transit from kernel domain
  			 * if executing initializers because they might start
  			 * before /sbin/init.
  			 */
  			domain = old_domain;
  		} else {
  			/* Normal domain transition. */
  			snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
  				 old_domain->domainname->name, rn.name);
  		}
  		break;
26a2a1c9e   Kentaro Takeda   Domain transition...
496
  	}
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
497
  	if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
26a2a1c9e   Kentaro Takeda   Domain transition...
498
  		goto done;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
499
  	domain = tomoyo_find_domain(tmp);
26a2a1c9e   Kentaro Takeda   Domain transition...
500
501
  	if (domain)
  		goto done;
17fcfbd9d   Tetsuo Handa   TOMOYO: Add inter...
502
503
504
  	if (is_enforce) {
  		int error = tomoyo_supervisor(&r, "# wants to create domain
  "
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
505
506
  					      "%s
  ", tmp);
17fcfbd9d   Tetsuo Handa   TOMOYO: Add inter...
507
508
509
510
511
  		if (error == TOMOYO_RETRY_REQUEST)
  			goto retry;
  		if (error < 0)
  			goto done;
  	}
e2bf69077   Tetsuo Handa   TOMOYO: Rename sy...
512
  	domain = tomoyo_assign_domain(tmp, old_domain->profile);
26a2a1c9e   Kentaro Takeda   Domain transition...
513
514
515
   done:
  	if (domain)
  		goto out;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
516
517
  	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.
  ", tmp);
26a2a1c9e   Kentaro Takeda   Domain transition...
518
519
520
  	if (is_enforce)
  		retval = -EPERM;
  	else
ea13ddbad   Tetsuo Handa   TOMOYO: Extract b...
521
  		old_domain->transition_failed = true;
26a2a1c9e   Kentaro Takeda   Domain transition...
522
   out:
56f8c9bc4   Tetsuo Handa   TOMOYO: Remove ne...
523
524
  	if (!domain)
  		domain = old_domain;
ec8e6a4e0   Tetsuo Handa   TOMOYO: Add refco...
525
526
  	/* Update reference count on "struct tomoyo_domain_info". */
  	atomic_inc(&domain->users);
56f8c9bc4   Tetsuo Handa   TOMOYO: Remove ne...
527
  	bprm->cred->security = domain;
c8c57e842   Tetsuo Handa   TOMOYO: Support l...
528
529
  	if (need_kfree)
  		kfree(rn.name);
8e2d39a16   Tetsuo Handa   TOMOYO: Remove us...
530
  	kfree(tmp);
26a2a1c9e   Kentaro Takeda   Domain transition...
531
532
  	return retval;
  }