0001
0002
0003
0004
0005
0006
0007
0008 #include "common.h"
0009 #include <linux/slab.h>
0010
0011
0012
0013
0014 static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
0015 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
0016 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
0017 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
0018 [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
0019 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
0020 [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
0021 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
0022 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
0023 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
0024 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
0025 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
0026 };
0027
0028
0029
0030
0031 const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
0032 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
0033 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
0034 };
0035
0036
0037
0038
0039 const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
0040 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
0041 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
0042 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
0043 };
0044
0045
0046
0047
0048
0049 const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
0050 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
0051 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
0052 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
0053 [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
0054 [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
0055 [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
0056 [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
0057 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
0058 };
0059
0060
0061
0062
0063
0064
0065
0066
0067 void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
0068 {
0069 tomoyo_put_group(ptr->group);
0070 tomoyo_put_name(ptr->filename);
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 const struct tomoyo_path_info *
0082 tomoyo_compare_name_union(const struct tomoyo_path_info *name,
0083 const struct tomoyo_name_union *ptr)
0084 {
0085 if (ptr->group)
0086 return tomoyo_path_matches_group(name, ptr->group);
0087 if (tomoyo_path_matches_pattern(name, ptr->filename))
0088 return ptr->filename;
0089 return NULL;
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099 void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
0100 {
0101 tomoyo_put_group(ptr->group);
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 bool tomoyo_compare_number_union(const unsigned long value,
0113 const struct tomoyo_number_union *ptr)
0114 {
0115 if (ptr->group)
0116 return tomoyo_number_matches_group(value, value, ptr->group);
0117 return value >= ptr->values[0] && value <= ptr->values[1];
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 static void tomoyo_add_slash(struct tomoyo_path_info *buf)
0131 {
0132 if (buf->is_dir)
0133 return;
0134
0135
0136
0137 strcat((char *) buf->name, "/");
0138 tomoyo_fill_path_info(buf);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
0150 {
0151 buf->name = tomoyo_realpath_from_path(path);
0152 if (buf->name) {
0153 tomoyo_fill_path_info(buf);
0154 return true;
0155 }
0156 return false;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166 static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
0167 {
0168 return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
0169 [r->param.path.operation],
0170 r->param.path.filename->name);
0171 }
0172
0173
0174
0175
0176
0177
0178
0179
0180 static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
0181 {
0182 return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
0183 [tomoyo_pp2mac[r->param.path2.operation]],
0184 r->param.path2.filename1->name,
0185 r->param.path2.filename2->name);
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195 static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
0196 {
0197 return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
0198 tomoyo_mac_keywords
0199 [tomoyo_pnnn2mac[r->param.mkdev.operation]],
0200 r->param.mkdev.filename->name,
0201 r->param.mkdev.mode, r->param.mkdev.major,
0202 r->param.mkdev.minor);
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
0213 {
0214 const u8 type = r->param.path_number.operation;
0215 u8 radix;
0216 char buffer[64];
0217
0218 switch (type) {
0219 case TOMOYO_TYPE_CREATE:
0220 case TOMOYO_TYPE_MKDIR:
0221 case TOMOYO_TYPE_MKFIFO:
0222 case TOMOYO_TYPE_MKSOCK:
0223 case TOMOYO_TYPE_CHMOD:
0224 radix = TOMOYO_VALUE_TYPE_OCTAL;
0225 break;
0226 case TOMOYO_TYPE_IOCTL:
0227 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
0228 break;
0229 default:
0230 radix = TOMOYO_VALUE_TYPE_DECIMAL;
0231 break;
0232 }
0233 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
0234 radix);
0235 return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
0236 [tomoyo_pn2mac[type]],
0237 r->param.path_number.filename->name, buffer);
0238 }
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
0253 const struct tomoyo_acl_info *ptr)
0254 {
0255 const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
0256 head);
0257
0258 if (acl->perm & (1 << r->param.path.operation)) {
0259 r->param.path.matched_path =
0260 tomoyo_compare_name_union(r->param.path.filename,
0261 &acl->name);
0262 return r->param.path.matched_path != NULL;
0263 }
0264 return false;
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
0276 const struct tomoyo_acl_info *ptr)
0277 {
0278 const struct tomoyo_path_number_acl *acl =
0279 container_of(ptr, typeof(*acl), head);
0280
0281 return (acl->perm & (1 << r->param.path_number.operation)) &&
0282 tomoyo_compare_number_union(r->param.path_number.number,
0283 &acl->number) &&
0284 tomoyo_compare_name_union(r->param.path_number.filename,
0285 &acl->name);
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
0297 const struct tomoyo_acl_info *ptr)
0298 {
0299 const struct tomoyo_path2_acl *acl =
0300 container_of(ptr, typeof(*acl), head);
0301
0302 return (acl->perm & (1 << r->param.path2.operation)) &&
0303 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
0304 && tomoyo_compare_name_union(r->param.path2.filename2,
0305 &acl->name2);
0306 }
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
0317 const struct tomoyo_acl_info *ptr)
0318 {
0319 const struct tomoyo_mkdev_acl *acl =
0320 container_of(ptr, typeof(*acl), head);
0321
0322 return (acl->perm & (1 << r->param.mkdev.operation)) &&
0323 tomoyo_compare_number_union(r->param.mkdev.mode,
0324 &acl->mode) &&
0325 tomoyo_compare_number_union(r->param.mkdev.major,
0326 &acl->major) &&
0327 tomoyo_compare_number_union(r->param.mkdev.minor,
0328 &acl->minor) &&
0329 tomoyo_compare_name_union(r->param.mkdev.filename,
0330 &acl->name);
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
0342 const struct tomoyo_acl_info *b)
0343 {
0344 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
0345 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
0346
0347 return tomoyo_same_name_union(&p1->name, &p2->name);
0348 }
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
0360 struct tomoyo_acl_info *b,
0361 const bool is_delete)
0362 {
0363 u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
0364 ->perm;
0365 u16 perm = READ_ONCE(*a_perm);
0366 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
0367
0368 if (is_delete)
0369 perm &= ~b_perm;
0370 else
0371 perm |= b_perm;
0372 WRITE_ONCE(*a_perm, perm);
0373 return !perm;
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 static int tomoyo_update_path_acl(const u16 perm,
0387 struct tomoyo_acl_param *param)
0388 {
0389 struct tomoyo_path_acl e = {
0390 .head.type = TOMOYO_TYPE_PATH_ACL,
0391 .perm = perm
0392 };
0393 int error;
0394
0395 if (!tomoyo_parse_name_union(param, &e.name))
0396 error = -EINVAL;
0397 else
0398 error = tomoyo_update_domain(&e.head, sizeof(e), param,
0399 tomoyo_same_path_acl,
0400 tomoyo_merge_path_acl);
0401 tomoyo_put_name_union(&e.name);
0402 return error;
0403 }
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
0414 const struct tomoyo_acl_info *b)
0415 {
0416 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
0417 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
0418
0419 return tomoyo_same_name_union(&p1->name, &p2->name) &&
0420 tomoyo_same_number_union(&p1->mode, &p2->mode) &&
0421 tomoyo_same_number_union(&p1->major, &p2->major) &&
0422 tomoyo_same_number_union(&p1->minor, &p2->minor);
0423 }
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
0435 struct tomoyo_acl_info *b,
0436 const bool is_delete)
0437 {
0438 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
0439 head)->perm;
0440 u8 perm = READ_ONCE(*a_perm);
0441 const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
0442 ->perm;
0443
0444 if (is_delete)
0445 perm &= ~b_perm;
0446 else
0447 perm |= b_perm;
0448 WRITE_ONCE(*a_perm, perm);
0449 return !perm;
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462 static int tomoyo_update_mkdev_acl(const u8 perm,
0463 struct tomoyo_acl_param *param)
0464 {
0465 struct tomoyo_mkdev_acl e = {
0466 .head.type = TOMOYO_TYPE_MKDEV_ACL,
0467 .perm = perm
0468 };
0469 int error;
0470
0471 if (!tomoyo_parse_name_union(param, &e.name) ||
0472 !tomoyo_parse_number_union(param, &e.mode) ||
0473 !tomoyo_parse_number_union(param, &e.major) ||
0474 !tomoyo_parse_number_union(param, &e.minor))
0475 error = -EINVAL;
0476 else
0477 error = tomoyo_update_domain(&e.head, sizeof(e), param,
0478 tomoyo_same_mkdev_acl,
0479 tomoyo_merge_mkdev_acl);
0480 tomoyo_put_name_union(&e.name);
0481 tomoyo_put_number_union(&e.mode);
0482 tomoyo_put_number_union(&e.major);
0483 tomoyo_put_number_union(&e.minor);
0484 return error;
0485 }
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
0496 const struct tomoyo_acl_info *b)
0497 {
0498 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
0499 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
0500
0501 return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
0502 tomoyo_same_name_union(&p1->name2, &p2->name2);
0503 }
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
0515 struct tomoyo_acl_info *b,
0516 const bool is_delete)
0517 {
0518 u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
0519 ->perm;
0520 u8 perm = READ_ONCE(*a_perm);
0521 const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
0522
0523 if (is_delete)
0524 perm &= ~b_perm;
0525 else
0526 perm |= b_perm;
0527 WRITE_ONCE(*a_perm, perm);
0528 return !perm;
0529 }
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 static int tomoyo_update_path2_acl(const u8 perm,
0542 struct tomoyo_acl_param *param)
0543 {
0544 struct tomoyo_path2_acl e = {
0545 .head.type = TOMOYO_TYPE_PATH2_ACL,
0546 .perm = perm
0547 };
0548 int error;
0549
0550 if (!tomoyo_parse_name_union(param, &e.name1) ||
0551 !tomoyo_parse_name_union(param, &e.name2))
0552 error = -EINVAL;
0553 else
0554 error = tomoyo_update_domain(&e.head, sizeof(e), param,
0555 tomoyo_same_path2_acl,
0556 tomoyo_merge_path2_acl);
0557 tomoyo_put_name_union(&e.name1);
0558 tomoyo_put_name_union(&e.name2);
0559 return error;
0560 }
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573 static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
0574 const struct tomoyo_path_info *filename)
0575 {
0576 int error;
0577
0578 r->type = tomoyo_p2mac[operation];
0579 r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
0580 if (r->mode == TOMOYO_CONFIG_DISABLED)
0581 return 0;
0582 r->param_type = TOMOYO_TYPE_PATH_ACL;
0583 r->param.path.filename = filename;
0584 r->param.path.operation = operation;
0585 do {
0586 tomoyo_check_acl(r, tomoyo_check_path_acl);
0587 error = tomoyo_audit_path_log(r);
0588 } while (error == TOMOYO_RETRY_REQUEST);
0589 return error;
0590 }
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 int tomoyo_execute_permission(struct tomoyo_request_info *r,
0603 const struct tomoyo_path_info *filename)
0604 {
0605
0606
0607
0608
0609
0610 r->type = TOMOYO_MAC_FILE_EXECUTE;
0611 r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
0612 r->param_type = TOMOYO_TYPE_PATH_ACL;
0613 r->param.path.filename = filename;
0614 r->param.path.operation = TOMOYO_TYPE_EXECUTE;
0615 tomoyo_check_acl(r, tomoyo_check_path_acl);
0616 r->ee->transition = r->matched_acl && r->matched_acl->cond ?
0617 r->matched_acl->cond->transit : NULL;
0618 if (r->mode != TOMOYO_CONFIG_DISABLED)
0619 return tomoyo_audit_path_log(r);
0620 return 0;
0621 }
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
0632 const struct tomoyo_acl_info *b)
0633 {
0634 const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
0635 head);
0636 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
0637 head);
0638
0639 return tomoyo_same_name_union(&p1->name, &p2->name) &&
0640 tomoyo_same_number_union(&p1->number, &p2->number);
0641 }
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
0653 struct tomoyo_acl_info *b,
0654 const bool is_delete)
0655 {
0656 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
0657 head)->perm;
0658 u8 perm = READ_ONCE(*a_perm);
0659 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
0660 ->perm;
0661
0662 if (is_delete)
0663 perm &= ~b_perm;
0664 else
0665 perm |= b_perm;
0666 WRITE_ONCE(*a_perm, perm);
0667 return !perm;
0668 }
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 static int tomoyo_update_path_number_acl(const u8 perm,
0679 struct tomoyo_acl_param *param)
0680 {
0681 struct tomoyo_path_number_acl e = {
0682 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
0683 .perm = perm
0684 };
0685 int error;
0686
0687 if (!tomoyo_parse_name_union(param, &e.name) ||
0688 !tomoyo_parse_number_union(param, &e.number))
0689 error = -EINVAL;
0690 else
0691 error = tomoyo_update_domain(&e.head, sizeof(e), param,
0692 tomoyo_same_path_number_acl,
0693 tomoyo_merge_path_number_acl);
0694 tomoyo_put_name_union(&e.name);
0695 tomoyo_put_number_union(&e.number);
0696 return error;
0697 }
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708 int tomoyo_path_number_perm(const u8 type, const struct path *path,
0709 unsigned long number)
0710 {
0711 struct tomoyo_request_info r;
0712 struct tomoyo_obj_info obj = {
0713 .path1 = { .mnt = path->mnt, .dentry = path->dentry },
0714 };
0715 int error = -ENOMEM;
0716 struct tomoyo_path_info buf;
0717 int idx;
0718
0719 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
0720 == TOMOYO_CONFIG_DISABLED || !path->dentry)
0721 return 0;
0722 idx = tomoyo_read_lock();
0723 if (!tomoyo_get_realpath(&buf, path))
0724 goto out;
0725 r.obj = &obj;
0726 if (type == TOMOYO_TYPE_MKDIR)
0727 tomoyo_add_slash(&buf);
0728 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
0729 r.param.path_number.operation = type;
0730 r.param.path_number.filename = &buf;
0731 r.param.path_number.number = number;
0732 do {
0733 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
0734 error = tomoyo_audit_path_number_log(&r);
0735 } while (error == TOMOYO_RETRY_REQUEST);
0736 kfree(buf.name);
0737 out:
0738 tomoyo_read_unlock(idx);
0739 if (r.mode != TOMOYO_CONFIG_ENFORCING)
0740 error = 0;
0741 return error;
0742 }
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
0754 const struct path *path, const int flag)
0755 {
0756 const u8 acc_mode = ACC_MODE(flag);
0757 int error = 0;
0758 struct tomoyo_path_info buf;
0759 struct tomoyo_request_info r;
0760 struct tomoyo_obj_info obj = {
0761 .path1 = { .mnt = path->mnt, .dentry = path->dentry },
0762 };
0763 int idx;
0764
0765 buf.name = NULL;
0766 r.mode = TOMOYO_CONFIG_DISABLED;
0767 idx = tomoyo_read_lock();
0768 if (acc_mode &&
0769 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
0770 != TOMOYO_CONFIG_DISABLED) {
0771 if (!tomoyo_get_realpath(&buf, path)) {
0772 error = -ENOMEM;
0773 goto out;
0774 }
0775 r.obj = &obj;
0776 if (acc_mode & MAY_READ)
0777 error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
0778 &buf);
0779 if (!error && (acc_mode & MAY_WRITE))
0780 error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
0781 TOMOYO_TYPE_APPEND :
0782 TOMOYO_TYPE_WRITE,
0783 &buf);
0784 }
0785 out:
0786 kfree(buf.name);
0787 tomoyo_read_unlock(idx);
0788 if (r.mode != TOMOYO_CONFIG_ENFORCING)
0789 error = 0;
0790 return error;
0791 }
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803 int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
0804 {
0805 struct tomoyo_request_info r;
0806 struct tomoyo_obj_info obj = {
0807 .path1 = { .mnt = path->mnt, .dentry = path->dentry },
0808 };
0809 int error;
0810 struct tomoyo_path_info buf;
0811 bool is_enforce;
0812 struct tomoyo_path_info symlink_target;
0813 int idx;
0814
0815 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
0816 == TOMOYO_CONFIG_DISABLED)
0817 return 0;
0818 is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
0819 error = -ENOMEM;
0820 buf.name = NULL;
0821 idx = tomoyo_read_lock();
0822 if (!tomoyo_get_realpath(&buf, path))
0823 goto out;
0824 r.obj = &obj;
0825 switch (operation) {
0826 case TOMOYO_TYPE_RMDIR:
0827 case TOMOYO_TYPE_CHROOT:
0828 tomoyo_add_slash(&buf);
0829 break;
0830 case TOMOYO_TYPE_SYMLINK:
0831 symlink_target.name = tomoyo_encode(target);
0832 if (!symlink_target.name)
0833 goto out;
0834 tomoyo_fill_path_info(&symlink_target);
0835 obj.symlink_target = &symlink_target;
0836 break;
0837 }
0838 error = tomoyo_path_permission(&r, operation, &buf);
0839 if (operation == TOMOYO_TYPE_SYMLINK)
0840 kfree(symlink_target.name);
0841 out:
0842 kfree(buf.name);
0843 tomoyo_read_unlock(idx);
0844 if (!is_enforce)
0845 error = 0;
0846 return error;
0847 }
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859 int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
0860 const unsigned int mode, unsigned int dev)
0861 {
0862 struct tomoyo_request_info r;
0863 struct tomoyo_obj_info obj = {
0864 .path1 = { .mnt = path->mnt, .dentry = path->dentry },
0865 };
0866 int error = -ENOMEM;
0867 struct tomoyo_path_info buf;
0868 int idx;
0869
0870 if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
0871 == TOMOYO_CONFIG_DISABLED)
0872 return 0;
0873 idx = tomoyo_read_lock();
0874 error = -ENOMEM;
0875 if (tomoyo_get_realpath(&buf, path)) {
0876 r.obj = &obj;
0877 dev = new_decode_dev(dev);
0878 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
0879 r.param.mkdev.filename = &buf;
0880 r.param.mkdev.operation = operation;
0881 r.param.mkdev.mode = mode;
0882 r.param.mkdev.major = MAJOR(dev);
0883 r.param.mkdev.minor = MINOR(dev);
0884 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
0885 error = tomoyo_audit_mkdev_log(&r);
0886 kfree(buf.name);
0887 }
0888 tomoyo_read_unlock(idx);
0889 if (r.mode != TOMOYO_CONFIG_ENFORCING)
0890 error = 0;
0891 return error;
0892 }
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903 int tomoyo_path2_perm(const u8 operation, const struct path *path1,
0904 const struct path *path2)
0905 {
0906 int error = -ENOMEM;
0907 struct tomoyo_path_info buf1;
0908 struct tomoyo_path_info buf2;
0909 struct tomoyo_request_info r;
0910 struct tomoyo_obj_info obj = {
0911 .path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
0912 .path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
0913 };
0914 int idx;
0915
0916 if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
0917 == TOMOYO_CONFIG_DISABLED)
0918 return 0;
0919 buf1.name = NULL;
0920 buf2.name = NULL;
0921 idx = tomoyo_read_lock();
0922 if (!tomoyo_get_realpath(&buf1, path1) ||
0923 !tomoyo_get_realpath(&buf2, path2))
0924 goto out;
0925 switch (operation) {
0926 case TOMOYO_TYPE_RENAME:
0927 case TOMOYO_TYPE_LINK:
0928 if (!d_is_dir(path1->dentry))
0929 break;
0930 fallthrough;
0931 case TOMOYO_TYPE_PIVOT_ROOT:
0932 tomoyo_add_slash(&buf1);
0933 tomoyo_add_slash(&buf2);
0934 break;
0935 }
0936 r.obj = &obj;
0937 r.param_type = TOMOYO_TYPE_PATH2_ACL;
0938 r.param.path2.operation = operation;
0939 r.param.path2.filename1 = &buf1;
0940 r.param.path2.filename2 = &buf2;
0941 do {
0942 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
0943 error = tomoyo_audit_path2_log(&r);
0944 } while (error == TOMOYO_RETRY_REQUEST);
0945 out:
0946 kfree(buf1.name);
0947 kfree(buf2.name);
0948 tomoyo_read_unlock(idx);
0949 if (r.mode != TOMOYO_CONFIG_ENFORCING)
0950 error = 0;
0951 return error;
0952 }
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962 static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
0963 const struct tomoyo_acl_info *b)
0964 {
0965 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
0966 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
0967
0968 return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
0969 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
0970 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
0971 tomoyo_same_number_union(&p1->flags, &p2->flags);
0972 }
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983 static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
0984 {
0985 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
0986 int error;
0987
0988 if (!tomoyo_parse_name_union(param, &e.dev_name) ||
0989 !tomoyo_parse_name_union(param, &e.dir_name) ||
0990 !tomoyo_parse_name_union(param, &e.fs_type) ||
0991 !tomoyo_parse_number_union(param, &e.flags))
0992 error = -EINVAL;
0993 else
0994 error = tomoyo_update_domain(&e.head, sizeof(e), param,
0995 tomoyo_same_mount_acl, NULL);
0996 tomoyo_put_name_union(&e.dev_name);
0997 tomoyo_put_name_union(&e.dir_name);
0998 tomoyo_put_name_union(&e.fs_type);
0999 tomoyo_put_number_union(&e.flags);
1000 return error;
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010
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 }