Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/tomoyo/file.c
54335 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* security/tomoyo/file.c
4
*
5
* Copyright (C) 2005-2011 NTT DATA CORPORATION
6
*/
7
8
#include "common.h"
9
#include <linux/slab.h>
10
11
/*
12
* Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
13
*/
14
static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
15
[TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
16
[TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
17
[TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
18
[TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
19
[TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
20
[TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
21
[TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
22
[TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
23
[TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
24
[TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
25
[TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
26
};
27
28
/*
29
* Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
30
*/
31
const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
32
[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
33
[TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
34
};
35
36
/*
37
* Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
38
*/
39
const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
40
[TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
41
[TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
42
[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
43
};
44
45
/*
46
* Mapping table from "enum tomoyo_path_number_acl_index" to
47
* "enum tomoyo_mac_index".
48
*/
49
const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
50
[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
51
[TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
52
[TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
53
[TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
54
[TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
55
[TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
56
[TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
57
[TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
58
};
59
60
/**
61
* tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
62
*
63
* @ptr: Pointer to "struct tomoyo_name_union".
64
*
65
* Returns nothing.
66
*/
67
void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
68
{
69
tomoyo_put_group(ptr->group);
70
tomoyo_put_name(ptr->filename);
71
}
72
73
/**
74
* tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
75
*
76
* @name: Pointer to "struct tomoyo_path_info".
77
* @ptr: Pointer to "struct tomoyo_name_union".
78
*
79
* Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
80
*/
81
const struct tomoyo_path_info *
82
tomoyo_compare_name_union(const struct tomoyo_path_info *name,
83
const struct tomoyo_name_union *ptr)
84
{
85
if (ptr->group)
86
return tomoyo_path_matches_group(name, ptr->group);
87
if (tomoyo_path_matches_pattern(name, ptr->filename))
88
return ptr->filename;
89
return NULL;
90
}
91
92
/**
93
* tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
94
*
95
* @ptr: Pointer to "struct tomoyo_number_union".
96
*
97
* Returns nothing.
98
*/
99
void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
100
{
101
tomoyo_put_group(ptr->group);
102
}
103
104
/**
105
* tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
106
*
107
* @value: Number to check.
108
* @ptr: Pointer to "struct tomoyo_number_union".
109
*
110
* Returns true if @value matches @ptr, false otherwise.
111
*/
112
bool tomoyo_compare_number_union(const unsigned long value,
113
const struct tomoyo_number_union *ptr)
114
{
115
if (ptr->group)
116
return tomoyo_number_matches_group(value, value, ptr->group);
117
return value >= ptr->values[0] && value <= ptr->values[1];
118
}
119
120
/**
121
* tomoyo_add_slash - Add trailing '/' if needed.
122
*
123
* @buf: Pointer to "struct tomoyo_path_info".
124
*
125
* Returns nothing.
126
*
127
* @buf must be generated by tomoyo_encode() because this function does not
128
* allocate memory for adding '/'.
129
*/
130
static void tomoyo_add_slash(struct tomoyo_path_info *buf)
131
{
132
if (buf->is_dir)
133
return;
134
/*
135
* This is OK because tomoyo_encode() reserves space for appending "/".
136
*/
137
strcat((char *) buf->name, "/");
138
tomoyo_fill_path_info(buf);
139
}
140
141
/**
142
* tomoyo_get_realpath - Get realpath.
143
*
144
* @buf: Pointer to "struct tomoyo_path_info".
145
* @path: Pointer to "struct path".
146
*
147
* Returns true on success, false otherwise.
148
*/
149
static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
150
{
151
buf->name = tomoyo_realpath_from_path(path);
152
if (buf->name) {
153
tomoyo_fill_path_info(buf);
154
return true;
155
}
156
return false;
157
}
158
159
/**
160
* tomoyo_audit_path_log - Audit path request log.
161
*
162
* @r: Pointer to "struct tomoyo_request_info".
163
*
164
* Returns 0 on success, negative value otherwise.
165
*/
166
static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
167
__must_hold_shared(&tomoyo_ss)
168
{
169
return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
170
[r->param.path.operation],
171
r->param.path.filename->name);
172
}
173
174
/**
175
* tomoyo_audit_path2_log - Audit path/path request log.
176
*
177
* @r: Pointer to "struct tomoyo_request_info".
178
*
179
* Returns 0 on success, negative value otherwise.
180
*/
181
static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
182
__must_hold_shared(&tomoyo_ss)
183
{
184
return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
185
[tomoyo_pp2mac[r->param.path2.operation]],
186
r->param.path2.filename1->name,
187
r->param.path2.filename2->name);
188
}
189
190
/**
191
* tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
192
*
193
* @r: Pointer to "struct tomoyo_request_info".
194
*
195
* Returns 0 on success, negative value otherwise.
196
*/
197
static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
198
__must_hold_shared(&tomoyo_ss)
199
{
200
return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
201
tomoyo_mac_keywords
202
[tomoyo_pnnn2mac[r->param.mkdev.operation]],
203
r->param.mkdev.filename->name,
204
r->param.mkdev.mode, r->param.mkdev.major,
205
r->param.mkdev.minor);
206
}
207
208
/**
209
* tomoyo_audit_path_number_log - Audit path/number request log.
210
*
211
* @r: Pointer to "struct tomoyo_request_info".
212
*
213
* Returns 0 on success, negative value otherwise.
214
*/
215
static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
216
__must_hold_shared(&tomoyo_ss)
217
{
218
const u8 type = r->param.path_number.operation;
219
u8 radix;
220
char buffer[64];
221
222
switch (type) {
223
case TOMOYO_TYPE_CREATE:
224
case TOMOYO_TYPE_MKDIR:
225
case TOMOYO_TYPE_MKFIFO:
226
case TOMOYO_TYPE_MKSOCK:
227
case TOMOYO_TYPE_CHMOD:
228
radix = TOMOYO_VALUE_TYPE_OCTAL;
229
break;
230
case TOMOYO_TYPE_IOCTL:
231
radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
232
break;
233
default:
234
radix = TOMOYO_VALUE_TYPE_DECIMAL;
235
break;
236
}
237
tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
238
radix);
239
return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
240
[tomoyo_pn2mac[type]],
241
r->param.path_number.filename->name, buffer);
242
}
243
244
/**
245
* tomoyo_check_path_acl - Check permission for path operation.
246
*
247
* @r: Pointer to "struct tomoyo_request_info".
248
* @ptr: Pointer to "struct tomoyo_acl_info".
249
*
250
* Returns true if granted, false otherwise.
251
*
252
* To be able to use wildcard for domain transition, this function sets
253
* matching entry on success. Since the caller holds tomoyo_read_lock(),
254
* it is safe to set matching entry.
255
*/
256
static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
257
const struct tomoyo_acl_info *ptr)
258
{
259
const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
260
head);
261
262
if (acl->perm & (1 << r->param.path.operation)) {
263
r->param.path.matched_path =
264
tomoyo_compare_name_union(r->param.path.filename,
265
&acl->name);
266
return r->param.path.matched_path != NULL;
267
}
268
return false;
269
}
270
271
/**
272
* tomoyo_check_path_number_acl - Check permission for path number operation.
273
*
274
* @r: Pointer to "struct tomoyo_request_info".
275
* @ptr: Pointer to "struct tomoyo_acl_info".
276
*
277
* Returns true if granted, false otherwise.
278
*/
279
static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
280
const struct tomoyo_acl_info *ptr)
281
{
282
const struct tomoyo_path_number_acl *acl =
283
container_of(ptr, typeof(*acl), head);
284
285
return (acl->perm & (1 << r->param.path_number.operation)) &&
286
tomoyo_compare_number_union(r->param.path_number.number,
287
&acl->number) &&
288
tomoyo_compare_name_union(r->param.path_number.filename,
289
&acl->name);
290
}
291
292
/**
293
* tomoyo_check_path2_acl - Check permission for path path operation.
294
*
295
* @r: Pointer to "struct tomoyo_request_info".
296
* @ptr: Pointer to "struct tomoyo_acl_info".
297
*
298
* Returns true if granted, false otherwise.
299
*/
300
static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
301
const struct tomoyo_acl_info *ptr)
302
{
303
const struct tomoyo_path2_acl *acl =
304
container_of(ptr, typeof(*acl), head);
305
306
return (acl->perm & (1 << r->param.path2.operation)) &&
307
tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
308
&& tomoyo_compare_name_union(r->param.path2.filename2,
309
&acl->name2);
310
}
311
312
/**
313
* tomoyo_check_mkdev_acl - Check permission for path number number number operation.
314
*
315
* @r: Pointer to "struct tomoyo_request_info".
316
* @ptr: Pointer to "struct tomoyo_acl_info".
317
*
318
* Returns true if granted, false otherwise.
319
*/
320
static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
321
const struct tomoyo_acl_info *ptr)
322
{
323
const struct tomoyo_mkdev_acl *acl =
324
container_of(ptr, typeof(*acl), head);
325
326
return (acl->perm & (1 << r->param.mkdev.operation)) &&
327
tomoyo_compare_number_union(r->param.mkdev.mode,
328
&acl->mode) &&
329
tomoyo_compare_number_union(r->param.mkdev.major,
330
&acl->major) &&
331
tomoyo_compare_number_union(r->param.mkdev.minor,
332
&acl->minor) &&
333
tomoyo_compare_name_union(r->param.mkdev.filename,
334
&acl->name);
335
}
336
337
/**
338
* tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
339
*
340
* @a: Pointer to "struct tomoyo_acl_info".
341
* @b: Pointer to "struct tomoyo_acl_info".
342
*
343
* Returns true if @a == @b except permission bits, false otherwise.
344
*/
345
static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
346
const struct tomoyo_acl_info *b)
347
{
348
const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
349
const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
350
351
return tomoyo_same_name_union(&p1->name, &p2->name);
352
}
353
354
/**
355
* tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
356
*
357
* @a: Pointer to "struct tomoyo_acl_info".
358
* @b: Pointer to "struct tomoyo_acl_info".
359
* @is_delete: True for @a &= ~@b, false for @a |= @b.
360
*
361
* Returns true if @a is empty, false otherwise.
362
*/
363
static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
364
struct tomoyo_acl_info *b,
365
const bool is_delete)
366
{
367
u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
368
->perm;
369
u16 perm = READ_ONCE(*a_perm);
370
const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
371
372
if (is_delete)
373
perm &= ~b_perm;
374
else
375
perm |= b_perm;
376
WRITE_ONCE(*a_perm, perm);
377
return !perm;
378
}
379
380
/**
381
* tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
382
*
383
* @perm: Permission.
384
* @param: Pointer to "struct tomoyo_acl_param".
385
*
386
* Returns 0 on success, negative value otherwise.
387
*
388
* Caller holds tomoyo_read_lock().
389
*/
390
static int tomoyo_update_path_acl(const u16 perm,
391
struct tomoyo_acl_param *param)
392
{
393
struct tomoyo_path_acl e = {
394
.head.type = TOMOYO_TYPE_PATH_ACL,
395
.perm = perm
396
};
397
int error;
398
399
if (!tomoyo_parse_name_union(param, &e.name))
400
error = -EINVAL;
401
else
402
error = tomoyo_update_domain(&e.head, sizeof(e), param,
403
tomoyo_same_path_acl,
404
tomoyo_merge_path_acl);
405
tomoyo_put_name_union(&e.name);
406
return error;
407
}
408
409
/**
410
* tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
411
*
412
* @a: Pointer to "struct tomoyo_acl_info".
413
* @b: Pointer to "struct tomoyo_acl_info".
414
*
415
* Returns true if @a == @b except permission bits, false otherwise.
416
*/
417
static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
418
const struct tomoyo_acl_info *b)
419
{
420
const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
421
const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
422
423
return tomoyo_same_name_union(&p1->name, &p2->name) &&
424
tomoyo_same_number_union(&p1->mode, &p2->mode) &&
425
tomoyo_same_number_union(&p1->major, &p2->major) &&
426
tomoyo_same_number_union(&p1->minor, &p2->minor);
427
}
428
429
/**
430
* tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
431
*
432
* @a: Pointer to "struct tomoyo_acl_info".
433
* @b: Pointer to "struct tomoyo_acl_info".
434
* @is_delete: True for @a &= ~@b, false for @a |= @b.
435
*
436
* Returns true if @a is empty, false otherwise.
437
*/
438
static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
439
struct tomoyo_acl_info *b,
440
const bool is_delete)
441
{
442
u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
443
head)->perm;
444
u8 perm = READ_ONCE(*a_perm);
445
const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
446
->perm;
447
448
if (is_delete)
449
perm &= ~b_perm;
450
else
451
perm |= b_perm;
452
WRITE_ONCE(*a_perm, perm);
453
return !perm;
454
}
455
456
/**
457
* tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
458
*
459
* @perm: Permission.
460
* @param: Pointer to "struct tomoyo_acl_param".
461
*
462
* Returns 0 on success, negative value otherwise.
463
*
464
* Caller holds tomoyo_read_lock().
465
*/
466
static int tomoyo_update_mkdev_acl(const u8 perm,
467
struct tomoyo_acl_param *param)
468
{
469
struct tomoyo_mkdev_acl e = {
470
.head.type = TOMOYO_TYPE_MKDEV_ACL,
471
.perm = perm
472
};
473
int error;
474
475
if (!tomoyo_parse_name_union(param, &e.name) ||
476
!tomoyo_parse_number_union(param, &e.mode) ||
477
!tomoyo_parse_number_union(param, &e.major) ||
478
!tomoyo_parse_number_union(param, &e.minor))
479
error = -EINVAL;
480
else
481
error = tomoyo_update_domain(&e.head, sizeof(e), param,
482
tomoyo_same_mkdev_acl,
483
tomoyo_merge_mkdev_acl);
484
tomoyo_put_name_union(&e.name);
485
tomoyo_put_number_union(&e.mode);
486
tomoyo_put_number_union(&e.major);
487
tomoyo_put_number_union(&e.minor);
488
return error;
489
}
490
491
/**
492
* tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
493
*
494
* @a: Pointer to "struct tomoyo_acl_info".
495
* @b: Pointer to "struct tomoyo_acl_info".
496
*
497
* Returns true if @a == @b except permission bits, false otherwise.
498
*/
499
static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
500
const struct tomoyo_acl_info *b)
501
{
502
const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
503
const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
504
505
return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
506
tomoyo_same_name_union(&p1->name2, &p2->name2);
507
}
508
509
/**
510
* tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
511
*
512
* @a: Pointer to "struct tomoyo_acl_info".
513
* @b: Pointer to "struct tomoyo_acl_info".
514
* @is_delete: True for @a &= ~@b, false for @a |= @b.
515
*
516
* Returns true if @a is empty, false otherwise.
517
*/
518
static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
519
struct tomoyo_acl_info *b,
520
const bool is_delete)
521
{
522
u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
523
->perm;
524
u8 perm = READ_ONCE(*a_perm);
525
const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
526
527
if (is_delete)
528
perm &= ~b_perm;
529
else
530
perm |= b_perm;
531
WRITE_ONCE(*a_perm, perm);
532
return !perm;
533
}
534
535
/**
536
* tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
537
*
538
* @perm: Permission.
539
* @param: Pointer to "struct tomoyo_acl_param".
540
*
541
* Returns 0 on success, negative value otherwise.
542
*
543
* Caller holds tomoyo_read_lock().
544
*/
545
static int tomoyo_update_path2_acl(const u8 perm,
546
struct tomoyo_acl_param *param)
547
{
548
struct tomoyo_path2_acl e = {
549
.head.type = TOMOYO_TYPE_PATH2_ACL,
550
.perm = perm
551
};
552
int error;
553
554
if (!tomoyo_parse_name_union(param, &e.name1) ||
555
!tomoyo_parse_name_union(param, &e.name2))
556
error = -EINVAL;
557
else
558
error = tomoyo_update_domain(&e.head, sizeof(e), param,
559
tomoyo_same_path2_acl,
560
tomoyo_merge_path2_acl);
561
tomoyo_put_name_union(&e.name1);
562
tomoyo_put_name_union(&e.name2);
563
return error;
564
}
565
566
/**
567
* tomoyo_path_permission - Check permission for single path operation.
568
*
569
* @r: Pointer to "struct tomoyo_request_info".
570
* @operation: Type of operation.
571
* @filename: Filename to check.
572
*
573
* Returns 0 on success, negative value otherwise.
574
*
575
* Caller holds tomoyo_read_lock().
576
*/
577
static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
578
const struct tomoyo_path_info *filename)
579
__must_hold_shared(&tomoyo_ss)
580
{
581
int error;
582
583
r->type = tomoyo_p2mac[operation];
584
r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
585
if (r->mode == TOMOYO_CONFIG_DISABLED)
586
return 0;
587
r->param_type = TOMOYO_TYPE_PATH_ACL;
588
r->param.path.filename = filename;
589
r->param.path.operation = operation;
590
do {
591
tomoyo_check_acl(r, tomoyo_check_path_acl);
592
error = tomoyo_audit_path_log(r);
593
} while (error == TOMOYO_RETRY_REQUEST);
594
return error;
595
}
596
597
/**
598
* tomoyo_execute_permission - Check permission for execute operation.
599
*
600
* @r: Pointer to "struct tomoyo_request_info".
601
* @filename: Filename to check.
602
*
603
* Returns 0 on success, negative value otherwise.
604
*
605
* Caller holds tomoyo_read_lock().
606
*/
607
int tomoyo_execute_permission(struct tomoyo_request_info *r,
608
const struct tomoyo_path_info *filename)
609
{
610
/*
611
* Unlike other permission checks, this check is done regardless of
612
* profile mode settings in order to check for domain transition
613
* preference.
614
*/
615
r->type = TOMOYO_MAC_FILE_EXECUTE;
616
r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
617
r->param_type = TOMOYO_TYPE_PATH_ACL;
618
r->param.path.filename = filename;
619
r->param.path.operation = TOMOYO_TYPE_EXECUTE;
620
tomoyo_check_acl(r, tomoyo_check_path_acl);
621
r->ee->transition = r->matched_acl && r->matched_acl->cond ?
622
r->matched_acl->cond->transit : NULL;
623
if (r->mode != TOMOYO_CONFIG_DISABLED)
624
return tomoyo_audit_path_log(r);
625
return 0;
626
}
627
628
/**
629
* tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
630
*
631
* @a: Pointer to "struct tomoyo_acl_info".
632
* @b: Pointer to "struct tomoyo_acl_info".
633
*
634
* Returns true if @a == @b except permission bits, false otherwise.
635
*/
636
static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
637
const struct tomoyo_acl_info *b)
638
{
639
const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
640
head);
641
const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
642
head);
643
644
return tomoyo_same_name_union(&p1->name, &p2->name) &&
645
tomoyo_same_number_union(&p1->number, &p2->number);
646
}
647
648
/**
649
* tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
650
*
651
* @a: Pointer to "struct tomoyo_acl_info".
652
* @b: Pointer to "struct tomoyo_acl_info".
653
* @is_delete: True for @a &= ~@b, false for @a |= @b.
654
*
655
* Returns true if @a is empty, false otherwise.
656
*/
657
static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
658
struct tomoyo_acl_info *b,
659
const bool is_delete)
660
{
661
u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
662
head)->perm;
663
u8 perm = READ_ONCE(*a_perm);
664
const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
665
->perm;
666
667
if (is_delete)
668
perm &= ~b_perm;
669
else
670
perm |= b_perm;
671
WRITE_ONCE(*a_perm, perm);
672
return !perm;
673
}
674
675
/**
676
* tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
677
*
678
* @perm: Permission.
679
* @param: Pointer to "struct tomoyo_acl_param".
680
*
681
* Returns 0 on success, negative value otherwise.
682
*/
683
static int tomoyo_update_path_number_acl(const u8 perm,
684
struct tomoyo_acl_param *param)
685
{
686
struct tomoyo_path_number_acl e = {
687
.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
688
.perm = perm
689
};
690
int error;
691
692
if (!tomoyo_parse_name_union(param, &e.name) ||
693
!tomoyo_parse_number_union(param, &e.number))
694
error = -EINVAL;
695
else
696
error = tomoyo_update_domain(&e.head, sizeof(e), param,
697
tomoyo_same_path_number_acl,
698
tomoyo_merge_path_number_acl);
699
tomoyo_put_name_union(&e.name);
700
tomoyo_put_number_union(&e.number);
701
return error;
702
}
703
704
/**
705
* tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
706
*
707
* @type: Type of operation.
708
* @path: Pointer to "struct path".
709
* @number: Number.
710
*
711
* Returns 0 on success, negative value otherwise.
712
*/
713
int tomoyo_path_number_perm(const u8 type, const struct path *path,
714
unsigned long number)
715
{
716
struct tomoyo_request_info r;
717
struct tomoyo_obj_info obj = {
718
.path1 = { .mnt = path->mnt, .dentry = path->dentry },
719
};
720
int error = -ENOMEM;
721
struct tomoyo_path_info buf;
722
int idx;
723
724
if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
725
== TOMOYO_CONFIG_DISABLED)
726
return 0;
727
idx = tomoyo_read_lock();
728
if (!tomoyo_get_realpath(&buf, path))
729
goto out;
730
r.obj = &obj;
731
if (type == TOMOYO_TYPE_MKDIR)
732
tomoyo_add_slash(&buf);
733
r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
734
r.param.path_number.operation = type;
735
r.param.path_number.filename = &buf;
736
r.param.path_number.number = number;
737
do {
738
tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
739
error = tomoyo_audit_path_number_log(&r);
740
} while (error == TOMOYO_RETRY_REQUEST);
741
kfree(buf.name);
742
out:
743
tomoyo_read_unlock(idx);
744
if (r.mode != TOMOYO_CONFIG_ENFORCING)
745
error = 0;
746
return error;
747
}
748
749
/**
750
* tomoyo_check_open_permission - Check permission for "read" and "write".
751
*
752
* @domain: Pointer to "struct tomoyo_domain_info".
753
* @path: Pointer to "struct path".
754
* @flag: Flags for open().
755
*
756
* Returns 0 on success, negative value otherwise.
757
*/
758
int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
759
const struct path *path, const int flag)
760
{
761
const u8 acc_mode = ACC_MODE(flag);
762
int error = 0;
763
struct tomoyo_path_info buf;
764
struct tomoyo_request_info r;
765
struct tomoyo_obj_info obj = {
766
.path1 = { .mnt = path->mnt, .dentry = path->dentry },
767
};
768
int idx;
769
770
buf.name = NULL;
771
r.mode = TOMOYO_CONFIG_DISABLED;
772
idx = tomoyo_read_lock();
773
if (acc_mode &&
774
tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
775
!= TOMOYO_CONFIG_DISABLED) {
776
if (!tomoyo_get_realpath(&buf, path)) {
777
error = -ENOMEM;
778
goto out;
779
}
780
r.obj = &obj;
781
if (acc_mode & MAY_READ)
782
error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
783
&buf);
784
if (!error && (acc_mode & MAY_WRITE))
785
error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
786
TOMOYO_TYPE_APPEND :
787
TOMOYO_TYPE_WRITE,
788
&buf);
789
}
790
out:
791
kfree(buf.name);
792
tomoyo_read_unlock(idx);
793
if (r.mode != TOMOYO_CONFIG_ENFORCING)
794
error = 0;
795
return error;
796
}
797
798
/**
799
* tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
800
*
801
* @operation: Type of operation.
802
* @path: Pointer to "struct path".
803
* @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
804
* NULL otherwise.
805
*
806
* Returns 0 on success, negative value otherwise.
807
*/
808
int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
809
{
810
struct tomoyo_request_info r;
811
struct tomoyo_obj_info obj = {
812
.path1 = { .mnt = path->mnt, .dentry = path->dentry },
813
};
814
int error;
815
struct tomoyo_path_info buf;
816
bool is_enforce;
817
struct tomoyo_path_info symlink_target;
818
int idx;
819
820
if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
821
== TOMOYO_CONFIG_DISABLED)
822
return 0;
823
is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
824
error = -ENOMEM;
825
buf.name = NULL;
826
idx = tomoyo_read_lock();
827
if (!tomoyo_get_realpath(&buf, path))
828
goto out;
829
r.obj = &obj;
830
switch (operation) {
831
case TOMOYO_TYPE_RMDIR:
832
case TOMOYO_TYPE_CHROOT:
833
tomoyo_add_slash(&buf);
834
break;
835
case TOMOYO_TYPE_SYMLINK:
836
symlink_target.name = tomoyo_encode(target);
837
if (!symlink_target.name)
838
goto out;
839
tomoyo_fill_path_info(&symlink_target);
840
obj.symlink_target = &symlink_target;
841
break;
842
}
843
error = tomoyo_path_permission(&r, operation, &buf);
844
if (operation == TOMOYO_TYPE_SYMLINK)
845
kfree(symlink_target.name);
846
out:
847
kfree(buf.name);
848
tomoyo_read_unlock(idx);
849
if (!is_enforce)
850
error = 0;
851
return error;
852
}
853
854
/**
855
* tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
856
*
857
* @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
858
* @path: Pointer to "struct path".
859
* @mode: Create mode.
860
* @dev: Device number.
861
*
862
* Returns 0 on success, negative value otherwise.
863
*/
864
int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
865
const unsigned int mode, unsigned int dev)
866
{
867
struct tomoyo_request_info r;
868
struct tomoyo_obj_info obj = {
869
.path1 = { .mnt = path->mnt, .dentry = path->dentry },
870
};
871
int error = -ENOMEM;
872
struct tomoyo_path_info buf;
873
int idx;
874
875
if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
876
== TOMOYO_CONFIG_DISABLED)
877
return 0;
878
idx = tomoyo_read_lock();
879
error = -ENOMEM;
880
if (tomoyo_get_realpath(&buf, path)) {
881
r.obj = &obj;
882
dev = new_decode_dev(dev);
883
r.param_type = TOMOYO_TYPE_MKDEV_ACL;
884
r.param.mkdev.filename = &buf;
885
r.param.mkdev.operation = operation;
886
r.param.mkdev.mode = mode;
887
r.param.mkdev.major = MAJOR(dev);
888
r.param.mkdev.minor = MINOR(dev);
889
tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
890
error = tomoyo_audit_mkdev_log(&r);
891
kfree(buf.name);
892
}
893
tomoyo_read_unlock(idx);
894
if (r.mode != TOMOYO_CONFIG_ENFORCING)
895
error = 0;
896
return error;
897
}
898
899
/**
900
* tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
901
*
902
* @operation: Type of operation.
903
* @path1: Pointer to "struct path".
904
* @path2: Pointer to "struct path".
905
*
906
* Returns 0 on success, negative value otherwise.
907
*/
908
int tomoyo_path2_perm(const u8 operation, const struct path *path1,
909
const struct path *path2)
910
{
911
int error = -ENOMEM;
912
struct tomoyo_path_info buf1;
913
struct tomoyo_path_info buf2;
914
struct tomoyo_request_info r;
915
struct tomoyo_obj_info obj = {
916
.path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
917
.path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
918
};
919
int idx;
920
921
if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
922
== TOMOYO_CONFIG_DISABLED)
923
return 0;
924
buf1.name = NULL;
925
buf2.name = NULL;
926
idx = tomoyo_read_lock();
927
if (!tomoyo_get_realpath(&buf1, path1) ||
928
!tomoyo_get_realpath(&buf2, path2))
929
goto out;
930
switch (operation) {
931
case TOMOYO_TYPE_RENAME:
932
case TOMOYO_TYPE_LINK:
933
if (!d_is_dir(path1->dentry))
934
break;
935
fallthrough;
936
case TOMOYO_TYPE_PIVOT_ROOT:
937
tomoyo_add_slash(&buf1);
938
tomoyo_add_slash(&buf2);
939
break;
940
}
941
r.obj = &obj;
942
r.param_type = TOMOYO_TYPE_PATH2_ACL;
943
r.param.path2.operation = operation;
944
r.param.path2.filename1 = &buf1;
945
r.param.path2.filename2 = &buf2;
946
do {
947
tomoyo_check_acl(&r, tomoyo_check_path2_acl);
948
error = tomoyo_audit_path2_log(&r);
949
} while (error == TOMOYO_RETRY_REQUEST);
950
out:
951
kfree(buf1.name);
952
kfree(buf2.name);
953
tomoyo_read_unlock(idx);
954
if (r.mode != TOMOYO_CONFIG_ENFORCING)
955
error = 0;
956
return error;
957
}
958
959
/**
960
* tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
961
*
962
* @a: Pointer to "struct tomoyo_acl_info".
963
* @b: Pointer to "struct tomoyo_acl_info".
964
*
965
* Returns true if @a == @b, false otherwise.
966
*/
967
static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
968
const struct tomoyo_acl_info *b)
969
{
970
const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
971
const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
972
973
return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
974
tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
975
tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
976
tomoyo_same_number_union(&p1->flags, &p2->flags);
977
}
978
979
/**
980
* tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
981
*
982
* @param: Pointer to "struct tomoyo_acl_param".
983
*
984
* Returns 0 on success, negative value otherwise.
985
*
986
* Caller holds tomoyo_read_lock().
987
*/
988
static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
989
{
990
struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
991
int error;
992
993
if (!tomoyo_parse_name_union(param, &e.dev_name) ||
994
!tomoyo_parse_name_union(param, &e.dir_name) ||
995
!tomoyo_parse_name_union(param, &e.fs_type) ||
996
!tomoyo_parse_number_union(param, &e.flags))
997
error = -EINVAL;
998
else
999
error = tomoyo_update_domain(&e.head, sizeof(e), param,
1000
tomoyo_same_mount_acl, NULL);
1001
tomoyo_put_name_union(&e.dev_name);
1002
tomoyo_put_name_union(&e.dir_name);
1003
tomoyo_put_name_union(&e.fs_type);
1004
tomoyo_put_number_union(&e.flags);
1005
return error;
1006
}
1007
1008
/**
1009
* tomoyo_write_file - Update file related list.
1010
*
1011
* @param: Pointer to "struct tomoyo_acl_param".
1012
*
1013
* Returns 0 on success, negative value otherwise.
1014
*
1015
* Caller holds tomoyo_read_lock().
1016
*/
1017
int tomoyo_write_file(struct tomoyo_acl_param *param)
1018
{
1019
u16 perm = 0;
1020
u8 type;
1021
const char *operation = tomoyo_read_token(param);
1022
1023
for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
1024
if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
1025
perm |= 1 << type;
1026
if (perm)
1027
return tomoyo_update_path_acl(perm, param);
1028
for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1029
if (tomoyo_permstr(operation,
1030
tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
1031
perm |= 1 << type;
1032
if (perm)
1033
return tomoyo_update_path2_acl(perm, param);
1034
for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1035
if (tomoyo_permstr(operation,
1036
tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
1037
perm |= 1 << type;
1038
if (perm)
1039
return tomoyo_update_path_number_acl(perm, param);
1040
for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1041
if (tomoyo_permstr(operation,
1042
tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
1043
perm |= 1 << type;
1044
if (perm)
1045
return tomoyo_update_mkdev_acl(perm, param);
1046
if (tomoyo_permstr(operation,
1047
tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
1048
return tomoyo_update_mount_acl(param);
1049
return -EINVAL;
1050
}
1051
1052