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