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