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: add fine grained af_unix mediation

Extend af_unix mediation to support fine grained controls based on
the type (abstract, anonymous, fs), the address, and the labeling
on the socket.

This allows for using socket addresses to label and the socket and
control which subjects can communicate.

The unix rule format follows standard apparmor rules except that fs
based unix sockets can be mediated by existing file rules. None fs
unix sockets can be mediated by a unix socket rule. Where The address
of an abstract unix domain socket begins with the @ character, similar
to how they are reported (as paths) by netstat -x. The address then
follows and may contain pattern matching and any characters including
the null character. In apparmor null characters must be specified by
using an escape sequence \000 or \x00. The pattern matching is the
same as is used by file path matching so * will not match / even
though it has no special meaning with in an abstract socket name. Eg.

allow unix addr=@*,

Autobound unix domain sockets have a unix sun_path assigned to them by
the kernel, as such specifying a policy based address is not possible.
The autobinding of sockets can be controlled by specifying the special
auto keyword. Eg.

allow unix addr=auto,

To indicate that the rule only applies to auto binding of unix domain
sockets. It is important to note this only applies to the bind
permission as once the socket is bound to an address it is
indistinguishable from a socket that have an addr bound with a
specified name. When the auto keyword is used with other permissions
or as part of a peer addr it will be replaced with a pattern that can
match an autobound socket. Eg. For some kernels

allow unix rw addr=auto,

It is important to note, this pattern may match abstract sockets that
were not autobound but have an addr that fits what is generated by the
kernel when autobinding a socket.

Anonymous unix domain sockets have no sun_path associated with the
socket address, however it can be specified with the special none
keyword to indicate the rule only applies to anonymous unix domain
sockets. Eg.

allow unix addr=none,

If the address component of a rule is not specified then the rule
applies to autobind, abstract and anonymous sockets.

The label on the socket can be compared using the standard label=
rule conditional. Eg.

allow unix addr=@foo peer=(label=bar),

see man apparmor.d for full syntax description.

Signed-off-by: John Johansen <john.johansen@canonical.com>

+1063 -58
+1 -1
security/apparmor/Makefile
··· 6 6 apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \ 7 7 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 8 8 resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ 9 - policy_compat.o 9 + policy_compat.o af_unix.o 10 10 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 11 11 12 12 obj-$(CONFIG_SECURITY_APPARMOR_KUNIT_TEST) += apparmor_policy_unpack_test.o
+702
security/apparmor/af_unix.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * AppArmor security module 4 + * 5 + * This file contains AppArmor af_unix fine grained mediation 6 + * 7 + * Copyright 2023 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <net/tcp_states.h> 16 + 17 + #include "include/audit.h" 18 + #include "include/af_unix.h" 19 + #include "include/apparmor.h" 20 + #include "include/file.h" 21 + #include "include/label.h" 22 + #include "include/path.h" 23 + #include "include/policy.h" 24 + #include "include/cred.h" 25 + 26 + 27 + static inline struct sock *aa_unix_sk(struct unix_sock *u) 28 + { 29 + return &u->sk; 30 + } 31 + 32 + static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred, 33 + struct aa_label *label, struct unix_sock *u) 34 + { 35 + AA_BUG(!label); 36 + AA_BUG(!u); 37 + AA_BUG(!is_unix_fs(aa_unix_sk(u))); 38 + 39 + if (unconfined(label) || !label_mediates(label, AA_CLASS_FILE)) 40 + return 0; 41 + 42 + mask &= NET_FS_PERMS; 43 + /* if !u->path.dentry socket is being shutdown - implicit delegation 44 + * until obj delegation is supported 45 + */ 46 + if (u->path.dentry) { 47 + /* the sunpath may not be valid for this ns so use the path */ 48 + struct path_cond cond = { u->path.dentry->d_inode->i_uid, 49 + u->path.dentry->d_inode->i_mode 50 + }; 51 + 52 + return aa_path_perm(op, subj_cred, label, &u->path, 53 + PATH_SOCK_COND, mask, &cond); 54 + } /* else implicitly delegated */ 55 + 56 + return 0; 57 + } 58 + 59 + /* match_addr special constants */ 60 + #define ABSTRACT_ADDR "\x00" /* abstract socket addr */ 61 + #define ANONYMOUS_ADDR "\x01" /* anonymous endpoint, no addr */ 62 + #define DISCONNECTED_ADDR "\x02" /* addr is another namespace */ 63 + #define SHUTDOWN_ADDR "\x03" /* path addr is shutdown and cleared */ 64 + #define FS_ADDR "/" /* path addr in fs */ 65 + 66 + static aa_state_t match_addr(struct aa_dfa *dfa, aa_state_t state, 67 + struct sockaddr_un *addr, int addrlen) 68 + { 69 + if (addr) 70 + /* include leading \0 */ 71 + state = aa_dfa_match_len(dfa, state, addr->sun_path, 72 + unix_addr_len(addrlen)); 73 + else 74 + state = aa_dfa_match_len(dfa, state, ANONYMOUS_ADDR, 1); 75 + /* todo: could change to out of band for cleaner separation */ 76 + state = aa_dfa_null_transition(dfa, state); 77 + 78 + return state; 79 + } 80 + 81 + static aa_state_t match_to_local(struct aa_policydb *policy, 82 + aa_state_t state, u32 request, 83 + int type, int protocol, 84 + struct sockaddr_un *addr, int addrlen, 85 + struct aa_perms **p, 86 + const char **info) 87 + { 88 + state = aa_match_to_prot(policy, state, request, PF_UNIX, type, 89 + protocol, NULL, info); 90 + if (state) { 91 + state = match_addr(policy->dfa, state, addr, addrlen); 92 + if (state) { 93 + /* todo: local label matching */ 94 + state = aa_dfa_null_transition(policy->dfa, state); 95 + if (!state) 96 + *info = "failed local label match"; 97 + } else { 98 + *info = "failed local address match"; 99 + } 100 + } 101 + 102 + return state; 103 + } 104 + 105 + static aa_state_t match_to_sk(struct aa_policydb *policy, 106 + aa_state_t state, u32 request, 107 + struct unix_sock *u, struct aa_perms **p, 108 + const char **info) 109 + { 110 + struct sockaddr_un *addr = NULL; 111 + int addrlen = 0; 112 + 113 + if (u->addr) { 114 + addr = u->addr->name; 115 + addrlen = u->addr->len; 116 + } 117 + 118 + return match_to_local(policy, state, request, u->sk.sk_type, 119 + u->sk.sk_protocol, addr, addrlen, p, info); 120 + } 121 + 122 + #define CMD_ADDR 1 123 + #define CMD_LISTEN 2 124 + #define CMD_OPT 4 125 + 126 + static aa_state_t match_to_cmd(struct aa_policydb *policy, aa_state_t state, 127 + u32 request, struct unix_sock *u, 128 + char cmd, struct aa_perms **p, 129 + const char **info) 130 + { 131 + AA_BUG(!p); 132 + 133 + state = match_to_sk(policy, state, request, u, p, info); 134 + if (state && !*p) { 135 + state = aa_dfa_match_len(policy->dfa, state, &cmd, 1); 136 + if (!state) 137 + *info = "failed cmd selection match"; 138 + } 139 + 140 + return state; 141 + } 142 + 143 + static aa_state_t match_to_peer(struct aa_policydb *policy, aa_state_t state, 144 + u32 request, struct unix_sock *u, 145 + struct sockaddr_un *peer_addr, int peer_addrlen, 146 + struct aa_perms **p, const char **info) 147 + { 148 + AA_BUG(!p); 149 + 150 + state = match_to_cmd(policy, state, request, u, CMD_ADDR, p, info); 151 + if (state && !*p) { 152 + state = match_addr(policy->dfa, state, peer_addr, peer_addrlen); 153 + if (!state) 154 + *info = "failed peer address match"; 155 + } 156 + 157 + return state; 158 + } 159 + 160 + static aa_state_t match_label(struct aa_profile *profile, 161 + struct aa_ruleset *rule, aa_state_t state, 162 + u32 request, struct aa_profile *peer, 163 + struct aa_perms *p, 164 + struct apparmor_audit_data *ad) 165 + { 166 + AA_BUG(!profile); 167 + AA_BUG(!peer); 168 + 169 + ad->peer = &peer->label; 170 + 171 + if (state && !p) { 172 + state = aa_dfa_match(rule->policy->dfa, state, 173 + peer->base.hname); 174 + if (!state) 175 + ad->info = "failed peer label match"; 176 + 177 + } 178 + 179 + return aa_do_perms(profile, rule->policy, state, request, p, ad); 180 + } 181 + 182 + 183 + /* unix sock creation comes before we know if the socket will be an fs 184 + * socket 185 + * v6 - semantics are handled by mapping in profile load 186 + * v7 - semantics require sock create for tasks creating an fs socket. 187 + * v8 - same as v7 188 + */ 189 + static int profile_create_perm(struct aa_profile *profile, int family, 190 + int type, int protocol, 191 + struct apparmor_audit_data *ad) 192 + { 193 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 194 + typeof(*rules), list); 195 + aa_state_t state; 196 + 197 + AA_BUG(!profile); 198 + AA_BUG(profile_unconfined(profile)); 199 + 200 + state = RULE_MEDIATES_NET(rules); 201 + if (state) { 202 + state = aa_match_to_prot(rules->policy, state, AA_MAY_CREATE, 203 + PF_UNIX, type, protocol, NULL, 204 + &ad->info); 205 + 206 + return aa_do_perms(profile, rules->policy, state, AA_MAY_CREATE, 207 + NULL, ad); 208 + } 209 + 210 + return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type, 211 + protocol); 212 + } 213 + 214 + static int profile_sk_perm(struct aa_profile *profile, 215 + struct apparmor_audit_data *ad, 216 + u32 request, struct sock *sk) 217 + { 218 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 219 + typeof(*rules), 220 + list); 221 + struct aa_perms *p = NULL; 222 + aa_state_t state; 223 + 224 + AA_BUG(!profile); 225 + AA_BUG(!sk); 226 + AA_BUG(is_unix_fs(sk)); 227 + AA_BUG(profile_unconfined(profile)); 228 + 229 + state = RULE_MEDIATES_NET(rules); 230 + if (state) { 231 + state = match_to_sk(rules->policy, state, request, unix_sk(sk), 232 + &p, &ad->info); 233 + 234 + return aa_do_perms(profile, rules->policy, state, request, p, 235 + ad); 236 + } 237 + 238 + return aa_profile_af_sk_perm(profile, ad, request, sk); 239 + } 240 + 241 + static int profile_bind_perm(struct aa_profile *profile, struct sock *sk, 242 + struct apparmor_audit_data *ad) 243 + { 244 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 245 + typeof(*rules), list); 246 + struct aa_perms *p = NULL; 247 + aa_state_t state; 248 + 249 + AA_BUG(!profile); 250 + AA_BUG(!sk); 251 + AA_BUG(!ad); 252 + AA_BUG(profile_unconfined(profile)); 253 + 254 + state = RULE_MEDIATES_NET(rules); 255 + if (state) { 256 + /* bind for abstract socket */ 257 + state = match_to_local(rules->policy, state, AA_MAY_BIND, 258 + sk->sk_type, sk->sk_protocol, 259 + unix_addr(ad->net.addr), 260 + ad->net.addrlen, 261 + &p, &ad->info); 262 + 263 + return aa_do_perms(profile, rules->policy, state, AA_MAY_BIND, 264 + p, ad); 265 + } 266 + 267 + return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk); 268 + } 269 + 270 + static int profile_listen_perm(struct aa_profile *profile, struct sock *sk, 271 + int backlog, struct apparmor_audit_data *ad) 272 + { 273 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 274 + typeof(*rules), list); 275 + struct aa_perms *p = NULL; 276 + aa_state_t state; 277 + 278 + AA_BUG(!profile); 279 + AA_BUG(!sk); 280 + AA_BUG(is_unix_fs(sk)); 281 + AA_BUG(!ad); 282 + AA_BUG(profile_unconfined(profile)); 283 + 284 + state = RULE_MEDIATES_NET(rules); 285 + if (state) { 286 + __be16 b = cpu_to_be16(backlog); 287 + 288 + state = match_to_cmd(rules->policy, state, AA_MAY_LISTEN, 289 + unix_sk(sk), CMD_LISTEN, &p, &ad->info); 290 + if (state && !p) { 291 + state = aa_dfa_match_len(rules->policy->dfa, state, 292 + (char *) &b, 2); 293 + if (!state) 294 + ad->info = "failed listen backlog match"; 295 + } 296 + return aa_do_perms(profile, rules->policy, state, AA_MAY_LISTEN, 297 + p, ad); 298 + } 299 + 300 + return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk); 301 + } 302 + 303 + static int profile_accept_perm(struct aa_profile *profile, 304 + struct sock *sk, 305 + struct apparmor_audit_data *ad) 306 + { 307 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 308 + typeof(*rules), list); 309 + struct aa_perms *p = NULL; 310 + aa_state_t state; 311 + 312 + AA_BUG(!profile); 313 + AA_BUG(!sk); 314 + AA_BUG(is_unix_fs(sk)); 315 + AA_BUG(!ad); 316 + AA_BUG(profile_unconfined(profile)); 317 + 318 + state = RULE_MEDIATES_NET(rules); 319 + if (state) { 320 + state = match_to_sk(rules->policy, state, AA_MAY_ACCEPT, 321 + unix_sk(sk), &p, &ad->info); 322 + 323 + return aa_do_perms(profile, rules->policy, state, AA_MAY_ACCEPT, 324 + p, ad); 325 + } 326 + 327 + return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk); 328 + } 329 + 330 + static int profile_opt_perm(struct aa_profile *profile, u32 request, 331 + struct sock *sk, int optname, 332 + struct apparmor_audit_data *ad) 333 + { 334 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 335 + typeof(*rules), list); 336 + struct aa_perms *p = NULL; 337 + aa_state_t state; 338 + 339 + AA_BUG(!profile); 340 + AA_BUG(!sk); 341 + AA_BUG(is_unix_fs(sk)); 342 + AA_BUG(!ad); 343 + AA_BUG(profile_unconfined(profile)); 344 + 345 + state = RULE_MEDIATES_NET(rules); 346 + if (state) { 347 + __be16 b = cpu_to_be16(optname); 348 + 349 + state = match_to_cmd(rules->policy, state, request, unix_sk(sk), 350 + CMD_OPT, &p, &ad->info); 351 + if (state && !p) { 352 + state = aa_dfa_match_len(rules->policy->dfa, state, 353 + (char *) &b, 2); 354 + if (!state) 355 + ad->info = "failed sockopt match"; 356 + } 357 + return aa_do_perms(profile, rules->policy, state, request, p, 358 + ad); 359 + } 360 + 361 + return aa_profile_af_sk_perm(profile, ad, request, sk); 362 + } 363 + 364 + /* null peer_label is allowed, in which case the peer_sk label is used */ 365 + static int profile_peer_perm(struct aa_profile *profile, u32 request, 366 + struct sock *sk, struct sock *peer_sk, 367 + struct aa_label *peer_label, 368 + struct apparmor_audit_data *ad) 369 + { 370 + struct aa_ruleset *rules = list_first_entry(&profile->rules, 371 + typeof(*rules), list); 372 + struct aa_perms *p = NULL; 373 + aa_state_t state; 374 + 375 + AA_BUG(!profile); 376 + AA_BUG(profile_unconfined(profile)); 377 + AA_BUG(!sk); 378 + AA_BUG(!peer_sk); 379 + AA_BUG(!ad); 380 + AA_BUG(is_unix_fs(peer_sk)); /* currently always calls unix_fs_perm */ 381 + 382 + state = RULE_MEDIATES_NET(rules); 383 + if (state) { 384 + struct aa_sk_ctx *peer_ctx = aa_sock(peer_sk); 385 + struct aa_profile *peerp; 386 + struct sockaddr_un *addr = NULL; 387 + int len = 0; 388 + 389 + if (unix_sk(peer_sk)->addr) { 390 + addr = unix_sk(peer_sk)->addr->name; 391 + len = unix_sk(peer_sk)->addr->len; 392 + } 393 + state = match_to_peer(rules->policy, state, request, 394 + unix_sk(sk), 395 + addr, len, &p, &ad->info); 396 + if (!peer_label) 397 + peer_label = peer_ctx->label; 398 + 399 + return fn_for_each_in_ns(peer_label, peerp, 400 + match_label(profile, rules, state, request, 401 + peerp, p, ad)); 402 + } 403 + 404 + return aa_profile_af_sk_perm(profile, ad, request, sk); 405 + } 406 + 407 + /* -------------------------------- */ 408 + 409 + int aa_unix_create_perm(struct aa_label *label, int family, int type, 410 + int protocol) 411 + { 412 + if (!unconfined(label)) { 413 + struct aa_profile *profile; 414 + DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family, 415 + type, protocol); 416 + 417 + return fn_for_each_confined(label, profile, 418 + profile_create_perm(profile, family, type, 419 + protocol, &ad)); 420 + } 421 + 422 + return 0; 423 + } 424 + 425 + int aa_unix_label_sk_perm(const struct cred *subj_cred, 426 + struct aa_label *label, const char *op, u32 request, 427 + struct sock *sk) 428 + { 429 + if (!unconfined(label)) { 430 + struct aa_profile *profile; 431 + DEFINE_AUDIT_SK(ad, op, subj_cred, sk); 432 + 433 + return fn_for_each_confined(label, profile, 434 + profile_sk_perm(profile, &ad, request, sk)); 435 + } 436 + return 0; 437 + } 438 + 439 + static int unix_label_sock_perm(const struct cred *subj_cred, 440 + struct aa_label *label, const char *op, 441 + u32 request, struct socket *sock) 442 + { 443 + if (unconfined(label)) 444 + return 0; 445 + if (is_unix_fs(sock->sk)) 446 + return unix_fs_perm(op, request, subj_cred, label, 447 + unix_sk(sock->sk)); 448 + 449 + return aa_unix_label_sk_perm(subj_cred, label, op, request, sock->sk); 450 + } 451 + 452 + /* revalidation, get/set attr, shutdown */ 453 + int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock) 454 + { 455 + struct aa_label *label; 456 + int error; 457 + 458 + label = begin_current_label_crit_section(); 459 + error = unix_label_sock_perm(current_cred(), label, op, request, sock); 460 + end_current_label_crit_section(label); 461 + 462 + return error; 463 + } 464 + 465 + static int valid_addr(struct sockaddr *addr, int addr_len) 466 + { 467 + struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; 468 + 469 + /* addr_len == offsetof(struct sockaddr_un, sun_path) is autobind */ 470 + if (addr_len < offsetof(struct sockaddr_un, sun_path) || 471 + addr_len > sizeof(*sunaddr)) 472 + return -EINVAL; 473 + return 0; 474 + } 475 + 476 + int aa_unix_bind_perm(struct socket *sock, struct sockaddr *addr, 477 + int addrlen) 478 + { 479 + struct aa_profile *profile; 480 + struct aa_label *label; 481 + int error = 0; 482 + 483 + error = valid_addr(addr, addrlen); 484 + if (error) 485 + return error; 486 + 487 + label = begin_current_label_crit_section(); 488 + /* fs bind is handled by mknod */ 489 + if (!(unconfined(label) || is_unix_addr_fs(addr, addrlen))) { 490 + DEFINE_AUDIT_SK(ad, OP_BIND, current_cred(), sock->sk); 491 + 492 + ad.net.addr = unix_addr(addr); 493 + ad.net.addrlen = addrlen; 494 + 495 + error = fn_for_each_confined(label, profile, 496 + profile_bind_perm(profile, sock->sk, &ad)); 497 + } 498 + end_current_label_crit_section(label); 499 + 500 + return error; 501 + } 502 + 503 + /* 504 + * unix connections are covered by the 505 + * - unix_stream_connect (stream) and unix_may_send hooks (dgram) 506 + * - fs connect is handled by open 507 + * This is just here to document this is not needed for af_unix 508 + * 509 + int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, 510 + int addrlen) 511 + { 512 + return 0; 513 + } 514 + */ 515 + 516 + int aa_unix_listen_perm(struct socket *sock, int backlog) 517 + { 518 + struct aa_profile *profile; 519 + struct aa_label *label; 520 + int error = 0; 521 + 522 + label = begin_current_label_crit_section(); 523 + if (!(unconfined(label) || is_unix_fs(sock->sk))) { 524 + DEFINE_AUDIT_SK(ad, OP_LISTEN, current_cred(), sock->sk); 525 + 526 + error = fn_for_each_confined(label, profile, 527 + profile_listen_perm(profile, sock->sk, 528 + backlog, &ad)); 529 + } 530 + end_current_label_crit_section(label); 531 + 532 + return error; 533 + } 534 + 535 + 536 + /* ability of sock to connect, not peer address binding */ 537 + int aa_unix_accept_perm(struct socket *sock, struct socket *newsock) 538 + { 539 + struct aa_profile *profile; 540 + struct aa_label *label; 541 + int error = 0; 542 + 543 + label = begin_current_label_crit_section(); 544 + if (!(unconfined(label) || is_unix_fs(sock->sk))) { 545 + DEFINE_AUDIT_SK(ad, OP_ACCEPT, current_cred(), sock->sk); 546 + 547 + error = fn_for_each_confined(label, profile, 548 + profile_accept_perm(profile, sock->sk, &ad)); 549 + } 550 + end_current_label_crit_section(label); 551 + 552 + return error; 553 + } 554 + 555 + 556 + /* 557 + * dgram handled by unix_may_sendmsg, right to send on stream done at connect 558 + * could do per msg unix_stream here, but connect + socket transfer is 559 + * sufficient. This is just here to document this is not needed for af_unix 560 + * 561 + * sendmsg, recvmsg 562 + int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, 563 + struct msghdr *msg, int size) 564 + { 565 + return 0; 566 + } 567 + */ 568 + 569 + int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, 570 + int level, int optname) 571 + { 572 + struct aa_profile *profile; 573 + struct aa_label *label; 574 + int error = 0; 575 + 576 + label = begin_current_label_crit_section(); 577 + if (!(unconfined(label) || is_unix_fs(sock->sk))) { 578 + DEFINE_AUDIT_SK(ad, op, current_cred(), sock->sk); 579 + 580 + error = fn_for_each_confined(label, profile, 581 + profile_opt_perm(profile, request, 582 + sock->sk, optname, &ad)); 583 + } 584 + end_current_label_crit_section(label); 585 + 586 + return error; 587 + } 588 + 589 + /** 590 + * 591 + * Requires: lock held on both @sk and @peer_sk 592 + * called by unix_stream_connect, unix_may_send 593 + */ 594 + int aa_unix_peer_perm(const struct cred *subj_cred, 595 + struct aa_label *label, const char *op, u32 request, 596 + struct sock *sk, struct sock *peer_sk, 597 + struct aa_label *peer_label) 598 + { 599 + struct unix_sock *peeru = unix_sk(peer_sk); 600 + struct unix_sock *u = unix_sk(sk); 601 + 602 + AA_BUG(!label); 603 + AA_BUG(!sk); 604 + AA_BUG(!peer_sk); 605 + 606 + if (is_unix_fs(aa_unix_sk(peeru))) { 607 + return unix_fs_perm(op, request, subj_cred, label, peeru); 608 + } else if (is_unix_fs(aa_unix_sk(u))) { 609 + return unix_fs_perm(op, request, subj_cred, label, u); 610 + } else if (!unconfined(label)) { 611 + struct aa_profile *profile; 612 + DEFINE_AUDIT_SK(ad, op, subj_cred, sk); 613 + 614 + ad.net.peer_sk = peer_sk; 615 + 616 + return fn_for_each_confined(label, profile, 617 + profile_peer_perm(profile, request, sk, 618 + peer_sk, peer_label, &ad)); 619 + } 620 + 621 + return 0; 622 + } 623 + 624 + static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) 625 + { 626 + if (unlikely(sk1 == sk2) || !sk2) { 627 + unix_state_lock(sk1); 628 + return; 629 + } 630 + if (sk1 < sk2) { 631 + unix_state_lock(sk1); 632 + unix_state_lock(sk2); 633 + } else { 634 + unix_state_lock(sk2); 635 + unix_state_lock(sk1); 636 + } 637 + } 638 + 639 + static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) 640 + { 641 + if (unlikely(sk1 == sk2) || !sk2) { 642 + unix_state_unlock(sk1); 643 + return; 644 + } 645 + unix_state_unlock(sk1); 646 + unix_state_unlock(sk2); 647 + } 648 + 649 + /* TODO: examine replacing double lock with cached addr */ 650 + 651 + int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, 652 + const char *op, u32 request, struct file *file) 653 + { 654 + struct socket *sock = (struct socket *) file->private_data; 655 + struct sock *peer_sk = NULL; 656 + u32 sk_req = request & ~NET_PEER_MASK; 657 + bool is_sk_fs; 658 + int error = 0; 659 + 660 + AA_BUG(!label); 661 + AA_BUG(!sock); 662 + AA_BUG(!sock->sk); 663 + AA_BUG(sock->sk->sk_family != PF_UNIX); 664 + 665 + /* TODO: update sock label with new task label */ 666 + unix_state_lock(sock->sk); 667 + peer_sk = unix_peer(sock->sk); 668 + if (peer_sk) 669 + sock_hold(peer_sk); 670 + 671 + is_sk_fs = is_unix_fs(sock->sk); 672 + if (is_sk_fs && peer_sk) 673 + sk_req = request; 674 + if (sk_req) 675 + error = unix_label_sock_perm(subj_cred, label, op, sk_req, 676 + sock); 677 + unix_state_unlock(sock->sk); 678 + if (!peer_sk) 679 + return error; 680 + 681 + unix_state_double_lock(sock->sk, peer_sk); 682 + if (!is_sk_fs && is_unix_fs(peer_sk)) { 683 + last_error(error, 684 + unix_fs_perm(op, request, subj_cred, label, 685 + unix_sk(peer_sk))); 686 + } else if (!is_sk_fs) { 687 + struct aa_sk_ctx *pctx = aa_sock(peer_sk); 688 + 689 + last_error(error, 690 + xcheck(aa_unix_peer_perm(subj_cred, label, op, 691 + MAY_READ | MAY_WRITE, 692 + sock->sk, peer_sk, NULL), 693 + aa_unix_peer_perm(file->f_cred, pctx->label, op, 694 + MAY_READ | MAY_WRITE, 695 + peer_sk, sock->sk, label))); 696 + } 697 + unix_state_double_unlock(sock->sk, peer_sk); 698 + 699 + sock_put(peer_sk); 700 + 701 + return error; 702 + }
+7
security/apparmor/apparmorfs.c
··· 2387 2387 { } 2388 2388 }; 2389 2389 2390 + static struct aa_sfs_entry aa_sfs_entry_dbus[] = { 2391 + AA_SFS_FILE_STRING("mask", "acquire send receive"), 2392 + { } 2393 + }; 2394 + 2390 2395 static struct aa_sfs_entry aa_sfs_entry_query_label[] = { 2391 2396 AA_SFS_FILE_STRING("perms", "allow deny audit quiet"), 2392 2397 AA_SFS_FILE_BOOLEAN("data", 1), ··· 2414 2409 AA_SFS_DIR("domain", aa_sfs_entry_domain), 2415 2410 AA_SFS_DIR("file", aa_sfs_entry_file), 2416 2411 AA_SFS_DIR("network_v8", aa_sfs_entry_network), 2412 + AA_SFS_DIR("network", aa_sfs_entry_networkv9), 2417 2413 AA_SFS_DIR("mount", aa_sfs_entry_mount), 2418 2414 AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 2419 2415 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), ··· 2422 2416 AA_SFS_DIR("caps", aa_sfs_entry_caps), 2423 2417 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 2424 2418 AA_SFS_DIR("signal", aa_sfs_entry_signal), 2419 + AA_SFS_DIR("dbus", aa_sfs_entry_dbus), 2425 2420 AA_SFS_DIR("query", aa_sfs_entry_query), 2426 2421 AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring), 2427 2422 { }
+9 -7
security/apparmor/file.c
··· 14 14 #include <linux/fs.h> 15 15 #include <linux/mount.h> 16 16 17 + #include "include/af_unix.h" 17 18 #include "include/apparmor.h" 18 19 #include "include/audit.h" 19 20 #include "include/cred.h" ··· 218 217 return state; 219 218 } 220 219 221 - static int __aa_path_perm(const char *op, const struct cred *subj_cred, 222 - struct aa_profile *profile, const char *name, 223 - u32 request, struct path_cond *cond, int flags, 224 - struct aa_perms *perms) 220 + int __aa_path_perm(const char *op, const struct cred *subj_cred, 221 + struct aa_profile *profile, const char *name, 222 + u32 request, struct path_cond *cond, int flags, 223 + struct aa_perms *perms) 225 224 { 226 225 struct aa_ruleset *rules = list_first_entry(&profile->rules, 227 226 typeof(*rules), list); 228 227 int e = 0; 229 228 230 - if (profile_unconfined(profile)) 229 + if (profile_unconfined(profile) || 230 + ((flags & PATH_SOCK_COND) && !RULE_MEDIATES_NET(rules))) 231 231 return 0; 232 232 aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], 233 233 name, cond, perms); ··· 551 549 return 0; 552 550 553 551 /* TODO: improve to skip profiles cached in flabel */ 554 - error = aa_sock_file_perm(subj_cred, label, op, request, sock); 552 + error = aa_sock_file_perm(subj_cred, label, op, request, file); 555 553 if (denied) { 556 554 /* TODO: improve to skip profiles checked above */ 557 555 /* check every profile in file label to is cached */ 558 556 last_error(error, aa_sock_file_perm(subj_cred, flabel, op, 559 - request, sock)); 557 + request, file)); 560 558 } 561 559 if (!error) 562 560 update_file_ctx(file_ctx(file), label, request);
+57
security/apparmor/include/af_unix.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * AppArmor security module 4 + * 5 + * This file contains AppArmor af_unix fine grained mediation 6 + * 7 + * Copyright 2023 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + #ifndef __AA_AF_UNIX_H 15 + 16 + #include <net/af_unix.h> 17 + 18 + #include "label.h" 19 + 20 + #define unix_addr(A) ((struct sockaddr_un *)(A)) 21 + #define unix_addr_len(L) ((L) - sizeof(sa_family_t)) 22 + #define unix_peer(sk) (unix_sk(sk)->peer) 23 + #define is_unix_addr_abstract_name(B) ((B)[0] == 0) 24 + #define is_unix_addr_anon(A, L) ((A) && unix_addr_len(L) <= 0) 25 + #define is_unix_addr_fs(A, L) (!is_unix_addr_anon(A, L) && \ 26 + !is_unix_addr_abstract_name(unix_addr(A)->sun_path)) 27 + 28 + #define is_unix_anonymous(U) (!unix_sk(U)->addr) 29 + #define is_unix_fs(U) (!is_unix_anonymous(U) && \ 30 + unix_sk(U)->addr->name->sun_path[0]) 31 + #define is_unix_connected(S) ((S)->state == SS_CONNECTED) 32 + 33 + 34 + int aa_unix_peer_perm(const struct cred *subj_cred, 35 + struct aa_label *label, const char *op, u32 request, 36 + struct sock *sk, struct sock *peer_sk, 37 + struct aa_label *peer_label); 38 + int aa_unix_label_sk_perm(const struct cred *subj_cred, 39 + struct aa_label *label, const char *op, u32 request, 40 + struct sock *sk); 41 + int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock); 42 + int aa_unix_create_perm(struct aa_label *label, int family, int type, 43 + int protocol); 44 + int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address, 45 + int addrlen); 46 + int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, 47 + int addrlen); 48 + int aa_unix_listen_perm(struct socket *sock, int backlog); 49 + int aa_unix_accept_perm(struct socket *sock, struct socket *newsock); 50 + int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, 51 + struct msghdr *msg, int size); 52 + int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, int level, 53 + int optname); 54 + int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, 55 + const char *op, u32 request, struct file *file); 56 + 57 + #endif /* __AA_AF_UNIX_H */
+1
security/apparmor/include/apparmor.h
··· 28 28 #define AA_CLASS_SIGNAL 10 29 29 #define AA_CLASS_XMATCH 11 30 30 #define AA_CLASS_NET 14 31 + #define AA_CLASS_NETV9 15 31 32 #define AA_CLASS_LABEL 16 32 33 #define AA_CLASS_POSIX_MQUEUE 17 33 34 #define AA_CLASS_MODULE 19
+4
security/apparmor/include/file.h
··· 84 84 const char *name, struct path_cond *cond, 85 85 struct aa_perms *perms); 86 86 87 + int __aa_path_perm(const char *op, const struct cred *subj_cred, 88 + struct aa_profile *profile, const char *name, 89 + u32 request, struct path_cond *cond, int flags, 90 + struct aa_perms *perms); 87 91 int aa_path_perm(const char *op, const struct cred *subj_cred, 88 92 struct aa_label *label, const struct path *path, 89 93 int flags, u32 request, struct path_cond *cond);
+11 -6
security/apparmor/include/net.h
··· 56 56 return sk->sk_security + apparmor_blob_sizes.lbs_sock; 57 57 } 58 58 59 - #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ 59 + #define DEFINE_AUDIT_NET(NAME, OP, CRED, SK, F, T, P) \ 60 60 struct lsm_network_audit NAME ## _net = { .sk = (SK), \ 61 61 .family = (F)}; \ 62 62 DEFINE_AUDIT_DATA(NAME, \ ··· 65 65 AA_CLASS_NET, \ 66 66 OP); \ 67 67 NAME.common.u.net = &(NAME ## _net); \ 68 + NAME.subj_cred = (CRED); \ 68 69 NAME.net.type = (T); \ 69 70 NAME.net.protocol = (P) 70 71 71 - #define DEFINE_AUDIT_SK(NAME, OP, SK) \ 72 - DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ 72 + #define DEFINE_AUDIT_SK(NAME, OP, CRED, SK) \ 73 + DEFINE_AUDIT_NET(NAME, OP, CRED, SK, (SK)->sk_family, (SK)->sk_type, \ 73 74 (SK)->sk_protocol) 74 75 75 76 ··· 82 81 }; 83 82 84 83 extern struct aa_sfs_entry aa_sfs_entry_network[]; 84 + extern struct aa_sfs_entry aa_sfs_entry_networkv9[]; 85 85 86 - /* passing in state returned by XXX_mediates(class) */ 86 + int aa_do_perms(struct aa_profile *profile, struct aa_policydb *policy, 87 + aa_state_t state, u32 request, struct aa_perms *p, 88 + struct apparmor_audit_data *ad); 89 + /* passing in state returned by XXX_mediates_AF() */ 87 90 aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state, 88 - u32 request, u16 family, int type, int protocol, 91 + u32 request, u16 af, int type, int protocol, 89 92 struct aa_perms **p, const char **info); 90 93 void audit_net_cb(struct audit_buffer *ab, void *va); 91 94 int aa_profile_af_perm(struct aa_profile *profile, ··· 110 105 111 106 int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, 112 107 const char *op, u32 request, 113 - struct socket *sock); 108 + struct file *file); 114 109 115 110 int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, 116 111 u32 secid, const struct sock *sk);
+1
security/apparmor/include/path.h
··· 13 13 14 14 enum path_flags { 15 15 PATH_IS_DIR = 0x1, /* path is a directory */ 16 + PATH_SOCK_COND = 0x2, 16 17 PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ 17 18 PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ 18 19 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
+2 -7
security/apparmor/include/policy.h
··· 304 304 rules->policy->start[0], &class, 1); 305 305 } 306 306 307 - static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) 307 + static inline aa_state_t RULE_MEDIATES_NET(struct aa_ruleset *rules) 308 308 { 309 - aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NET); 310 - __be16 be_af = cpu_to_be16(AF); 311 - 312 - if (!state) 313 - return DFA_NOMATCH; 314 - return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); 309 + return RULE_MEDIATES(rules, AA_CLASS_NET); 315 310 } 316 311 317 312 static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head,
+156 -7
security/apparmor/lsm.c
··· 26 26 #include <uapi/linux/mount.h> 27 27 #include <uapi/linux/lsm.h> 28 28 29 + #include "include/af_unix.h" 29 30 #include "include/apparmor.h" 30 31 #include "include/apparmorfs.h" 31 32 #include "include/audit.h" ··· 1089 1088 new->peer = aa_get_label(ctx->peer); 1090 1089 } 1091 1090 1091 + static int unix_connect_perm(const struct cred *cred, struct aa_label *label, 1092 + struct sock *sk, struct sock *peer_sk) 1093 + { 1094 + struct aa_sk_ctx *peer_ctx = aa_sock(peer_sk); 1095 + int error; 1096 + 1097 + error = aa_unix_peer_perm(cred, label, OP_CONNECT, 1098 + (AA_MAY_CONNECT | AA_MAY_SEND | AA_MAY_RECEIVE), 1099 + sk, peer_sk, NULL); 1100 + if (!is_unix_fs(peer_sk)) { 1101 + last_error(error, 1102 + aa_unix_peer_perm(cred, 1103 + peer_ctx->label, OP_CONNECT, 1104 + (AA_MAY_ACCEPT | AA_MAY_SEND | AA_MAY_RECEIVE), 1105 + peer_sk, sk, label)); 1106 + } 1107 + 1108 + return error; 1109 + } 1110 + 1111 + static void unix_connect_peers(struct aa_sk_ctx *sk_ctx, 1112 + struct aa_sk_ctx *peer_ctx) 1113 + { 1114 + /* Cross reference the peer labels for SO_PEERSEC */ 1115 + aa_put_label(peer_ctx->peer); 1116 + aa_put_label(sk_ctx->peer); 1117 + 1118 + peer_ctx->peer = aa_get_label(sk_ctx->label); 1119 + sk_ctx->peer = aa_get_label(peer_ctx->label); 1120 + } 1121 + 1122 + /** 1123 + * apparmor_unix_stream_connect - check perms before making unix domain conn 1124 + * 1125 + * peer is locked when this hook is called 1126 + */ 1127 + static int apparmor_unix_stream_connect(struct sock *sk, struct sock *peer_sk, 1128 + struct sock *newsk) 1129 + { 1130 + struct aa_sk_ctx *sk_ctx = aa_sock(sk); 1131 + struct aa_sk_ctx *peer_ctx = aa_sock(peer_sk); 1132 + struct aa_sk_ctx *new_ctx = aa_sock(newsk); 1133 + struct aa_label *label; 1134 + int error; 1135 + 1136 + label = __begin_current_label_crit_section(); 1137 + error = unix_connect_perm(current_cred(), label, sk, peer_sk); 1138 + __end_current_label_crit_section(label); 1139 + 1140 + if (error) 1141 + return error; 1142 + 1143 + /* newsk doesn't go through post_create */ 1144 + AA_BUG(new_ctx->label); 1145 + new_ctx->label = aa_get_label(peer_ctx->label); 1146 + 1147 + /* Cross reference the peer labels for SO_PEERSEC */ 1148 + unix_connect_peers(sk_ctx, new_ctx); 1149 + 1150 + return 0; 1151 + } 1152 + 1153 + /** 1154 + * apparmor_unix_may_send - check perms before conn or sending unix dgrams 1155 + * 1156 + * sock and peer are locked when this hook is called 1157 + * 1158 + * called by: dgram_connect peer setup but path not copied to newsk 1159 + */ 1160 + static int apparmor_unix_may_send(struct socket *sock, struct socket *peer) 1161 + { 1162 + struct aa_sk_ctx *peer_ctx = aa_sock(peer->sk); 1163 + struct aa_label *label; 1164 + int error; 1165 + 1166 + label = __begin_current_label_crit_section(); 1167 + error = xcheck(aa_unix_peer_perm(current_cred(), 1168 + label, OP_SENDMSG, AA_MAY_SEND, 1169 + sock->sk, peer->sk, NULL), 1170 + aa_unix_peer_perm(peer->file ? peer->file->f_cred : NULL, 1171 + peer_ctx->label, OP_SENDMSG, 1172 + AA_MAY_RECEIVE, 1173 + peer->sk, sock->sk, label)); 1174 + __end_current_label_crit_section(label); 1175 + 1176 + return error; 1177 + } 1178 + 1092 1179 static int apparmor_socket_create(int family, int type, int protocol, int kern) 1093 1180 { 1094 1181 struct aa_label *label; ··· 1189 1100 1190 1101 label = begin_current_label_crit_section(); 1191 1102 if (!unconfined(label)) { 1192 - error = aa_af_perm(current_cred(), label, OP_CREATE, 1193 - AA_MAY_CREATE, family, type, protocol); 1103 + if (family == PF_UNIX) 1104 + error = aa_unix_create_perm(label, family, type, 1105 + protocol); 1106 + else 1107 + error = aa_af_perm(current_cred(), label, OP_CREATE, 1108 + AA_MAY_CREATE, family, type, 1109 + protocol); 1194 1110 } 1195 1111 end_current_label_crit_section(label); 1196 1112 ··· 1237 1143 return 0; 1238 1144 } 1239 1145 1146 + static int apparmor_socket_socketpair(struct socket *socka, 1147 + struct socket *sockb) 1148 + { 1149 + struct aa_sk_ctx *a_ctx = aa_sock(socka->sk); 1150 + struct aa_sk_ctx *b_ctx = aa_sock(sockb->sk); 1151 + struct aa_label *label; 1152 + int error = 0; 1153 + 1154 + aa_put_label(a_ctx->label); 1155 + aa_put_label(b_ctx->label); 1156 + 1157 + label = begin_current_label_crit_section(); 1158 + a_ctx->label = aa_get_label(label); 1159 + b_ctx->label = aa_get_label(label); 1160 + 1161 + if (socka->sk->sk_family == PF_UNIX) { 1162 + /* unix socket pairs by-pass unix_stream_connect */ 1163 + if (!error) 1164 + unix_connect_peers(a_ctx, b_ctx); 1165 + } 1166 + end_current_label_crit_section(label); 1167 + 1168 + return error; 1169 + } 1170 + 1171 + /** 1172 + * apparmor_socket_bind - check perms before bind addr to socket 1173 + */ 1240 1174 static int apparmor_socket_bind(struct socket *sock, 1241 1175 struct sockaddr *address, int addrlen) 1242 1176 { ··· 1273 1151 AA_BUG(!address); 1274 1152 AA_BUG(in_interrupt()); 1275 1153 1154 + if (sock->sk->sk_family == PF_UNIX) 1155 + return aa_unix_bind_perm(sock, address, addrlen); 1276 1156 return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk); 1277 1157 } 1278 1158 ··· 1286 1162 AA_BUG(!address); 1287 1163 AA_BUG(in_interrupt()); 1288 1164 1165 + /* PF_UNIX goes through unix_stream_connect && unix_may_send */ 1166 + if (sock->sk->sk_family == PF_UNIX) 1167 + return 0; 1289 1168 return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk); 1290 1169 } 1291 1170 ··· 1298 1171 AA_BUG(!sock->sk); 1299 1172 AA_BUG(in_interrupt()); 1300 1173 1174 + if (sock->sk->sk_family == PF_UNIX) 1175 + return aa_unix_listen_perm(sock, backlog); 1301 1176 return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk); 1302 1177 } 1303 1178 ··· 1314 1185 AA_BUG(!newsock); 1315 1186 AA_BUG(in_interrupt()); 1316 1187 1188 + if (sock->sk->sk_family == PF_UNIX) 1189 + return aa_unix_accept_perm(sock, newsock); 1317 1190 return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk); 1318 1191 } 1319 1192 ··· 1327 1196 AA_BUG(!msg); 1328 1197 AA_BUG(in_interrupt()); 1329 1198 1199 + /* PF_UNIX goes through unix_may_send */ 1200 + if (sock->sk->sk_family == PF_UNIX) 1201 + return 0; 1330 1202 return aa_sk_perm(op, request, sock->sk); 1331 1203 } 1332 1204 ··· 1352 1218 AA_BUG(!sock->sk); 1353 1219 AA_BUG(in_interrupt()); 1354 1220 1221 + if (sock->sk->sk_family == PF_UNIX) 1222 + return aa_unix_sock_perm(op, request, sock); 1355 1223 return aa_sk_perm(op, request, sock->sk); 1356 1224 } 1357 1225 ··· 1375 1239 AA_BUG(!sock->sk); 1376 1240 AA_BUG(in_interrupt()); 1377 1241 1242 + if (sock->sk->sk_family == PF_UNIX) 1243 + return aa_unix_opt_perm(op, request, sock, level, optname); 1378 1244 return aa_sk_perm(op, request, sock->sk); 1379 1245 } 1380 1246 ··· 1430 1292 #endif 1431 1293 1432 1294 1433 - static struct aa_label *sk_peer_label(struct sock *sk) 1295 + static struct aa_label *sk_peer_get_label(struct sock *sk) 1434 1296 { 1435 1297 struct aa_sk_ctx *ctx = aa_sock(sk); 1298 + struct aa_label *label = ERR_PTR(-ENOPROTOOPT); 1436 1299 1437 1300 if (ctx->peer) 1438 - return ctx->peer; 1301 + return aa_get_label(ctx->peer); 1439 1302 1440 - return ERR_PTR(-ENOPROTOOPT); 1303 + if (sk->sk_family != PF_UNIX) 1304 + return ERR_PTR(-ENOPROTOOPT); 1305 + 1306 + return label; 1441 1307 } 1442 1308 1443 1309 /** ··· 1464 1322 struct aa_label *peer; 1465 1323 1466 1324 label = begin_current_label_crit_section(); 1467 - peer = sk_peer_label(sock->sk); 1325 + peer = sk_peer_get_label(sock->sk); 1468 1326 if (IS_ERR(peer)) { 1469 1327 error = PTR_ERR(peer); 1470 1328 goto done; ··· 1475 1333 /* don't include terminating \0 in slen, it breaks some apps */ 1476 1334 if (slen < 0) { 1477 1335 error = -ENOMEM; 1478 - goto done; 1336 + goto done_put; 1479 1337 } 1480 1338 if (slen > len) { 1481 1339 error = -ERANGE; ··· 1487 1345 done_len: 1488 1346 if (copy_to_sockptr(optlen, &slen, sizeof(slen))) 1489 1347 error = -EFAULT; 1348 + 1349 + done_put: 1350 + aa_put_label(peer); 1490 1351 done: 1491 1352 end_current_label_crit_section(label); 1492 1353 kfree(name); ··· 1601 1456 LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 1602 1457 LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 1603 1458 1459 + LSM_HOOK_INIT(unix_stream_connect, apparmor_unix_stream_connect), 1460 + LSM_HOOK_INIT(unix_may_send, apparmor_unix_may_send), 1461 + 1604 1462 LSM_HOOK_INIT(socket_create, apparmor_socket_create), 1605 1463 LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), 1464 + LSM_HOOK_INIT(socket_socketpair, apparmor_socket_socketpair), 1606 1465 LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), 1607 1466 LSM_HOOK_INIT(socket_connect, apparmor_socket_connect), 1608 1467 LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
+112 -30
security/apparmor/net.c
··· 8 8 * Copyright 2009-2017 Canonical Ltd. 9 9 */ 10 10 11 + #include "include/af_unix.h" 11 12 #include "include/apparmor.h" 12 13 #include "include/audit.h" 13 14 #include "include/cred.h" ··· 22 21 23 22 struct aa_sfs_entry aa_sfs_entry_network[] = { 24 23 AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 24 + { } 25 + }; 26 + 27 + struct aa_sfs_entry aa_sfs_entry_networkv9[] = { 28 + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 29 + AA_SFS_FILE_BOOLEAN("af_unix", 1), 25 30 { } 26 31 }; 27 32 ··· 73 66 "unknown", 74 67 }; 75 68 69 + static void audit_unix_addr(struct audit_buffer *ab, const char *str, 70 + struct sockaddr_un *addr, int addrlen) 71 + { 72 + int len = unix_addr_len(addrlen); 73 + 74 + if (!addr || len <= 0) { 75 + audit_log_format(ab, " %s=none", str); 76 + } else if (addr->sun_path[0]) { 77 + audit_log_format(ab, " %s=", str); 78 + audit_log_untrustedstring(ab, addr->sun_path); 79 + } else { 80 + audit_log_format(ab, " %s=\"@", str); 81 + if (audit_string_contains_control(&addr->sun_path[1], len - 1)) 82 + audit_log_n_hex(ab, &addr->sun_path[1], len - 1); 83 + else 84 + audit_log_format(ab, "%.*s", len - 1, 85 + &addr->sun_path[1]); 86 + audit_log_format(ab, "\""); 87 + } 88 + } 89 + 90 + static void audit_unix_sk_addr(struct audit_buffer *ab, const char *str, 91 + const struct sock *sk) 92 + { 93 + const struct unix_sock *u = unix_sk(sk); 94 + 95 + if (u && u->addr) 96 + audit_unix_addr(ab, str, u->addr->name, u->addr->len); 97 + else 98 + audit_unix_addr(ab, str, NULL, 0); 99 + } 76 100 77 101 /* audit callback for net specific fields */ 78 102 void audit_net_cb(struct audit_buffer *ab, void *va) ··· 111 73 struct common_audit_data *sa = va; 112 74 struct apparmor_audit_data *ad = aad(sa); 113 75 114 - if (address_family_names[sa->u.net->family]) 76 + if (address_family_names[ad->common.u.net->family]) 115 77 audit_log_format(ab, " family=\"%s\"", 116 - address_family_names[sa->u.net->family]); 78 + address_family_names[ad->common.u.net->family]); 117 79 else 118 80 audit_log_format(ab, " family=\"unknown(%d)\"", 119 - sa->u.net->family); 81 + ad->common.u.net->family); 120 82 if (sock_type_names[ad->net.type]) 121 83 audit_log_format(ab, " sock_type=\"%s\"", 122 84 sock_type_names[ad->net.type]); ··· 136 98 net_mask_names, NET_PERMS_MASK); 137 99 } 138 100 } 101 + if (ad->common.u.net->family == PF_UNIX) { 102 + if ((ad->request & ~NET_PEER_MASK) && ad->net.addr) 103 + audit_unix_addr(ab, "addr", 104 + unix_addr(ad->net.addr), 105 + ad->net.addrlen); 106 + else 107 + audit_unix_sk_addr(ab, "addr", ad->common.u.net->sk); 108 + if (ad->request & NET_PEER_MASK) { 109 + if (ad->net.addr) 110 + audit_unix_addr(ab, "peer_addr", 111 + unix_addr(ad->net.addr), 112 + ad->net.addrlen); 113 + else 114 + audit_unix_sk_addr(ab, "peer_addr", 115 + ad->net.peer_sk); 116 + } 117 + } 139 118 if (ad->peer) { 140 119 audit_log_format(ab, " peer="); 141 120 aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, ··· 161 106 } 162 107 163 108 /* standard permission lookup pattern - supports early bailout */ 164 - static int do_perms(struct aa_profile *profile, struct aa_policydb *policy, 165 - unsigned int state, u32 request, 166 - struct aa_perms *p, struct apparmor_audit_data *ad) 109 + int aa_do_perms(struct aa_profile *profile, struct aa_policydb *policy, 110 + aa_state_t state, u32 request, 111 + struct aa_perms *p, struct apparmor_audit_data *ad) 167 112 { 168 113 struct aa_perms perms; 169 114 ··· 195 140 return p; 196 141 } 197 142 198 - /* passing in state returned by PROFILE_MEDIATES_AF */ 143 + static aa_state_t aa_dfa_match_be16(struct aa_dfa *dfa, aa_state_t state, 144 + u16 data) 145 + { 146 + __be16 buffer = cpu_to_be16(data); 147 + 148 + return aa_dfa_match_len(dfa, state, (char *) &buffer, 2); 149 + } 150 + 151 + /** 152 + * aa_match_to_prot - match the af, type, protocol triplet 153 + * @policy: policy being matched 154 + * @state: state to start in 155 + * @request: permissions being requested, ignored if @p == NULL 156 + * @af: socket address family 157 + * @type: socket type 158 + * @protocol: socket protocol 159 + * @p: output - pointer to permission associated with match 160 + * @info: output - pointer to string describing failure 161 + * 162 + * RETURNS: state match stopped in. 163 + * 164 + * If @(p) is assigned a value the returned state will be the 165 + * corresponding state. Will not set @p on failure or if match completes 166 + * only if an early match occurs 167 + */ 199 168 aa_state_t aa_match_to_prot(struct aa_policydb *policy, aa_state_t state, 200 - u32 request, u16 family, int type, int protocol, 169 + u32 request, u16 af, int type, int protocol, 201 170 struct aa_perms **p, const char **info) 202 171 { 203 - __be16 buffer; 204 - 205 - buffer = cpu_to_be16(family); 206 - state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer, 2); 172 + state = aa_dfa_match_be16(policy->dfa, state, (u16)af); 207 173 if (!state) { 208 174 *info = "failed af match"; 209 - return DFA_NOMATCH; 175 + return state; 210 176 } 211 - buffer = cpu_to_be16((u16)type); 212 - state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer, 2); 213 - if (!state) 177 + state = aa_dfa_match_be16(policy->dfa, state, (u16)type); 178 + if (state) { 179 + if (p) 180 + *p = early_match(policy, state, request); 181 + if (!p || !*p) { 182 + state = aa_dfa_match_be16(policy->dfa, state, (u16)protocol); 183 + if (!state) 184 + *info = "failed protocol match"; 185 + } 186 + } else { 214 187 *info = "failed type match"; 215 - *p = early_match(policy, state, request); 216 - if (!*p) { 217 - buffer = cpu_to_be16((u16)protocol); 218 - state = aa_dfa_match_len(policy->dfa, state, (char *) &buffer, 219 - 2); 220 - if (!state) 221 - *info = "failed protocol match"; 222 188 } 189 + 223 190 return state; 224 191 } 225 192 ··· 259 182 AA_BUG(type < 0 || type >= SOCK_MAX); 260 183 AA_BUG(profile_unconfined(profile)); 261 184 262 - state = RULE_MEDIATES(rules, AA_CLASS_NET); 185 + if (profile_unconfined(profile)) 186 + return 0; 187 + state = RULE_MEDIATES_NET(rules); 263 188 if (!state) 264 189 return 0; 265 - 266 190 state = aa_match_to_prot(rules->policy, state, request, family, type, 267 191 protocol, &p, &ad->info); 268 - return do_perms(profile, rules->policy, state, request, p, ad); 192 + return aa_do_perms(profile, rules->policy, state, request, p, ad); 269 193 } 270 194 271 195 int aa_af_perm(const struct cred *subj_cred, struct aa_label *label, 272 196 const char *op, u32 request, u16 family, int type, int protocol) 273 197 { 274 198 struct aa_profile *profile; 275 - DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol); 199 + DEFINE_AUDIT_NET(ad, op, subj_cred, NULL, family, type, protocol); 276 200 277 201 return fn_for_each_confined(label, profile, 278 202 aa_profile_af_perm(profile, &ad, request, family, ··· 293 215 294 216 if (ctx->label != kernel_t && !unconfined(label)) { 295 217 struct aa_profile *profile; 296 - DEFINE_AUDIT_SK(ad, op, sk); 218 + DEFINE_AUDIT_SK(ad, op, subj_cred, sk); 297 219 298 220 ad.subj_cred = subj_cred; 299 221 error = fn_for_each_confined(label, profile, ··· 321 243 322 244 323 245 int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, 324 - const char *op, u32 request, struct socket *sock) 246 + const char *op, u32 request, struct file *file) 325 247 { 248 + struct socket *sock = (struct socket *) file->private_data; 249 + 326 250 AA_BUG(!label); 327 251 AA_BUG(!sock); 328 252 AA_BUG(!sock->sk); 329 253 254 + if (sock->sk->sk_family == PF_UNIX) 255 + return aa_unix_file_perm(subj_cred, label, op, request, file); 330 256 return aa_label_sk_perm(subj_cred, label, op, request, sock->sk); 331 257 } 332 258 ··· 395 313 u32 secid, const struct sock *sk) 396 314 { 397 315 struct aa_profile *profile; 398 - DEFINE_AUDIT_SK(ad, op, sk); 316 + DEFINE_AUDIT_SK(ad, op, NULL, sk); 399 317 400 318 return fn_for_each_confined(label, profile, 401 319 aa_secmark_perm(profile, request, secid,