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