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