Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

apparmor: fix regression in fs based unix sockets when using old abi

Policy loaded using abi 7 socket mediation was not being applied
correctly in all cases. In some cases with fs based unix sockets a
subset of permissions where allowed when they should have been denied.

This was happening because the check for if the socket was an fs based
unix socket came before the abi check. But the abi check is where the
correct path is selected, so having the fs unix socket check occur
early would cause the wrong code path to be used.

Fix this by pushing the fs unix to be done after the abi check.

Fixes: dcd7a559411e ("apparmor: gate make fine grained unix mediation behind v9 abi")
Signed-off-by: John Johansen <john.johansen@canonical.com>

+71 -51
+71 -48
security/apparmor/af_unix.c
··· 221 221 222 222 static int profile_sk_perm(struct aa_profile *profile, 223 223 struct apparmor_audit_data *ad, 224 - u32 request, struct sock *sk) 224 + u32 request, struct sock *sk, struct path *path) 225 225 { 226 226 struct aa_ruleset *rules = list_first_entry(&profile->rules, 227 227 typeof(*rules), ··· 231 231 232 232 AA_BUG(!profile); 233 233 AA_BUG(!sk); 234 - AA_BUG(is_unix_fs(sk)); 235 234 AA_BUG(profile_unconfined(profile)); 236 235 237 236 state = RULE_MEDIATES_v9NET(rules); 238 237 if (state) { 238 + if (is_unix_fs(sk)) 239 + return unix_fs_perm(ad->op, request, ad->subj_cred, 240 + &profile->label, 241 + &unix_sk(sk)->path); 242 + 239 243 state = match_to_sk(rules->policy, state, request, unix_sk(sk), 240 244 &p, &ad->info); 241 245 ··· 265 261 266 262 state = RULE_MEDIATES_v9NET(rules); 267 263 if (state) { 264 + if (is_unix_addr_fs(ad->net.addr, ad->net.addrlen)) 265 + /* under v7-9 fs hook handles bind */ 266 + return 0; 268 267 /* bind for abstract socket */ 269 268 state = match_to_local(rules->policy, state, AA_MAY_BIND, 270 269 sk->sk_type, sk->sk_protocol, ··· 292 285 293 286 AA_BUG(!profile); 294 287 AA_BUG(!sk); 295 - AA_BUG(is_unix_fs(sk)); 296 288 AA_BUG(!ad); 297 289 AA_BUG(profile_unconfined(profile)); 298 290 299 291 state = RULE_MEDIATES_v9NET(rules); 300 292 if (state) { 301 293 __be16 b = cpu_to_be16(backlog); 294 + 295 + if (is_unix_fs(sk)) 296 + return unix_fs_perm(ad->op, AA_MAY_LISTEN, 297 + ad->subj_cred, &profile->label, 298 + &unix_sk(sk)->path); 302 299 303 300 state = match_to_cmd(rules->policy, state, AA_MAY_LISTEN, 304 301 unix_sk(sk), CMD_LISTEN, &p, &ad->info); ··· 330 319 331 320 AA_BUG(!profile); 332 321 AA_BUG(!sk); 333 - AA_BUG(is_unix_fs(sk)); 334 322 AA_BUG(!ad); 335 323 AA_BUG(profile_unconfined(profile)); 336 324 337 325 state = RULE_MEDIATES_v9NET(rules); 338 326 if (state) { 327 + if (is_unix_fs(sk)) 328 + return unix_fs_perm(ad->op, AA_MAY_ACCEPT, 329 + ad->subj_cred, &profile->label, 330 + &unix_sk(sk)->path); 331 + 339 332 state = match_to_sk(rules->policy, state, AA_MAY_ACCEPT, 340 333 unix_sk(sk), &p, &ad->info); 341 334 ··· 361 346 362 347 AA_BUG(!profile); 363 348 AA_BUG(!sk); 364 - AA_BUG(is_unix_fs(sk)); 365 349 AA_BUG(!ad); 366 350 AA_BUG(profile_unconfined(profile)); 367 351 368 352 state = RULE_MEDIATES_v9NET(rules); 369 353 if (state) { 370 354 __be16 b = cpu_to_be16(optname); 355 + if (is_unix_fs(sk)) 356 + return unix_fs_perm(ad->op, request, 357 + ad->subj_cred, &profile->label, 358 + &unix_sk(sk)->path); 371 359 372 360 state = match_to_cmd(rules->policy, state, request, unix_sk(sk), 373 361 CMD_OPT, &p, &ad->info); ··· 389 371 390 372 /* null peer_label is allowed, in which case the peer_sk label is used */ 391 373 static int profile_peer_perm(struct aa_profile *profile, u32 request, 392 - struct sock *sk, struct sockaddr_un *peer_addr, 393 - int peer_addrlen, 374 + struct sock *sk, struct path *path, 375 + struct sockaddr_un *peer_addr, 376 + int peer_addrlen, struct path *peer_path, 394 377 struct aa_label *peer_label, 395 378 struct apparmor_audit_data *ad) 396 379 { ··· 410 391 if (state) { 411 392 struct aa_profile *peerp; 412 393 394 + if (peer_path) 395 + return unix_fs_perm(ad->op, request, ad->subj_cred, 396 + &profile->label, peer_path); 397 + else if (path) 398 + return unix_fs_perm(ad->op, request, ad->subj_cred, 399 + &profile->label, path); 413 400 state = match_to_peer(rules->policy, state, request, 414 401 unix_sk(sk), 415 402 peer_addr, peer_addrlen, &p, &ad->info); ··· 446 421 return 0; 447 422 } 448 423 449 - int aa_unix_label_sk_perm(const struct cred *subj_cred, struct aa_label *label, 450 - const char *op, u32 request, struct sock *sk) 424 + static int aa_unix_label_sk_perm(const struct cred *subj_cred, 425 + struct aa_label *label, 426 + const char *op, u32 request, struct sock *sk, 427 + struct path *path) 451 428 { 452 429 if (!unconfined(label)) { 453 430 struct aa_profile *profile; 454 431 DEFINE_AUDIT_SK(ad, op, subj_cred, sk); 455 432 456 433 return fn_for_each_confined(label, profile, 457 - profile_sk_perm(profile, &ad, request, sk)); 434 + profile_sk_perm(profile, &ad, request, sk, 435 + path)); 458 436 } 459 437 return 0; 460 438 } ··· 469 441 int error; 470 442 471 443 label = begin_current_label_crit_section(); 472 - if (is_unix_fs(sock->sk)) 473 - error = unix_fs_perm(op, request, current_cred(), label, 474 - &unix_sk(sock->sk)->path); 475 - else 476 - error = aa_unix_label_sk_perm(current_cred(), label, op, 477 - request, sock->sk); 444 + error = aa_unix_label_sk_perm(current_cred(), label, op, 445 + request, sock->sk, 446 + is_unix_fs(sock->sk) ? &unix_sk(sock->sk)->path : NULL); 478 447 end_current_label_crit_section(label); 479 448 480 449 return error; ··· 501 476 502 477 label = begin_current_label_crit_section(); 503 478 /* fs bind is handled by mknod */ 504 - if (!(unconfined(label) || is_unix_addr_fs(addr, addrlen))) { 479 + if (!unconfined(label)) { 505 480 DEFINE_AUDIT_SK(ad, OP_BIND, current_cred(), sock->sk); 506 481 507 482 ad.net.addr = unix_addr(addr); ··· 535 510 int error = 0; 536 511 537 512 label = begin_current_label_crit_section(); 538 - if (!(unconfined(label) || is_unix_fs(sock->sk))) { 513 + if (!unconfined(label)) { 539 514 DEFINE_AUDIT_SK(ad, OP_LISTEN, current_cred(), sock->sk); 540 515 541 516 error = fn_for_each_confined(label, profile, ··· 556 531 int error = 0; 557 532 558 533 label = begin_current_label_crit_section(); 559 - if (!(unconfined(label) || is_unix_fs(sock->sk))) { 534 + if (!unconfined(label)) { 560 535 DEFINE_AUDIT_SK(ad, OP_ACCEPT, current_cred(), sock->sk); 561 536 562 537 error = fn_for_each_confined(label, profile, ··· 589 564 int error = 0; 590 565 591 566 label = begin_current_label_crit_section(); 592 - if (!(unconfined(label) || is_unix_fs(sock->sk))) { 567 + if (!unconfined(label)) { 593 568 DEFINE_AUDIT_SK(ad, op, current_cred(), sock->sk); 594 569 595 570 error = fn_for_each_confined(label, profile, 596 - profile_opt_perm(profile, request, 597 - sock->sk, optname, &ad)); 571 + profile_opt_perm(profile, request, sock->sk, 572 + optname, &ad)); 598 573 } 599 574 end_current_label_crit_section(label); 600 575 ··· 603 578 604 579 static int unix_peer_perm(const struct cred *subj_cred, 605 580 struct aa_label *label, const char *op, u32 request, 606 - struct sock *sk, struct sockaddr_un *peer_addr, 607 - int peer_addrlen, struct aa_label *peer_label) 581 + struct sock *sk, struct path *path, 582 + struct sockaddr_un *peer_addr, int peer_addrlen, 583 + struct path *peer_path, struct aa_label *peer_label) 608 584 { 609 585 struct aa_profile *profile; 610 586 DEFINE_AUDIT_SK(ad, op, subj_cred, sk); ··· 614 588 ad.net.peer.addrlen = peer_addrlen; 615 589 616 590 return fn_for_each_confined(label, profile, 617 - profile_peer_perm(profile, request, sk, 618 - peer_addr, peer_addrlen, peer_label, &ad)); 591 + profile_peer_perm(profile, request, sk, path, 592 + peer_addr, peer_addrlen, peer_path, 593 + peer_label, &ad)); 619 594 } 620 595 621 596 /** ··· 631 604 { 632 605 struct unix_sock *peeru = unix_sk(peer_sk); 633 606 struct unix_sock *u = unix_sk(sk); 607 + int plen; 608 + struct sockaddr_un *paddr = aa_sunaddr(unix_sk(peer_sk), &plen); 634 609 635 610 AA_BUG(!label); 636 611 AA_BUG(!sk); 637 612 AA_BUG(!peer_sk); 638 613 AA_BUG(!peer_label); 639 614 640 - if (is_unix_fs(aa_unix_sk(peeru))) { 641 - return unix_fs_perm(op, request, subj_cred, label, 642 - &peeru->path); 643 - } else if (is_unix_fs(aa_unix_sk(u))) { 644 - return unix_fs_perm(op, request, subj_cred, label, &u->path); 645 - } else if (!unconfined(label)) { 646 - int plen; 647 - struct sockaddr_un *paddr = aa_sunaddr(unix_sk(peer_sk), 648 - &plen); 649 - 650 - return unix_peer_perm(subj_cred, label, op, request, 651 - sk, paddr, plen, peer_label); 652 - } 653 - 654 - return 0; 615 + return unix_peer_perm(subj_cred, label, op, request, sk, 616 + is_unix_fs(sk) ? &u->path : NULL, 617 + paddr, plen, 618 + is_unix_fs(peer_sk) ? &peeru->path : NULL, 619 + peer_label); 655 620 } 656 621 657 622 /* This fn is only checked if something has changed in the security ··· 684 665 if (is_sk_fs && peer_sk) 685 666 sk_req = request; 686 667 if (sk_req) { 687 - if (is_sk_fs) 688 - error = unix_fs_perm(op, sk_req, subj_cred, label, 689 - &path); 690 - else 691 668 error = aa_unix_label_sk_perm(subj_cred, label, op, 692 - sk_req, sock->sk); 669 + sk_req, sock->sk, 670 + is_sk_fs ? &path : NULL); 693 671 } 694 672 if (!peer_sk) 695 673 goto out; ··· 699 683 if (!is_sk_fs && is_unix_fs(peer_sk)) { 700 684 last_error(error, 701 685 unix_fs_perm(op, request, subj_cred, label, 702 - &peer_path)); 686 + is_unix_fs(peer_sk) ? &peer_path : NULL)); 703 687 } else if (!is_sk_fs) { 704 688 struct aa_sk_ctx *pctx = aa_sock(peer_sk); 705 689 ··· 709 693 last_error(error, 710 694 xcheck(unix_peer_perm(subj_cred, label, op, 711 695 MAY_READ | MAY_WRITE, sock->sk, 696 + is_sk_fs ? &path : NULL, 712 697 peer_addr, peer_addrlen, 698 + is_unix_fs(peer_sk) ? 699 + &peer_path : NULL, 713 700 pctx->label), 714 701 unix_peer_perm(file->f_cred, pctx->label, op, 715 702 MAY_READ | MAY_WRITE, peer_sk, 716 - addr, addrlen, label))); 703 + is_unix_fs(peer_sk) ? 704 + &peer_path : NULL, 705 + addr, addrlen, 706 + is_sk_fs ? &path : NULL, 707 + label))); 717 708 } 718 709 sock_put(peer_sk); 719 710
-3
security/apparmor/include/af_unix.h
··· 36 36 struct aa_label *label, const char *op, u32 request, 37 37 struct sock *sk, struct sock *peer_sk, 38 38 struct aa_label *peer_label); 39 - int aa_unix_label_sk_perm(const struct cred *subj_cred, 40 - struct aa_label *label, const char *op, u32 request, 41 - struct sock *sk); 42 39 int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock); 43 40 int aa_unix_create_perm(struct aa_label *label, int family, int type, 44 41 int protocol);