| 1 |
|
| 2 | |
| 3 | * AppArmor security module
|
| 4 | *
|
| 5 | * This file contains AppArmor inet fine grained mediation
|
| 6 | *
|
| 7 | * Copyright 2024 Canonical Ltd.
|
| 8 | *
|
| 9 |
|
| 10 |
|
| 11 | #include <net/tcp_states.h>
|
| 12 |
|
| 13 | #include "include/audit.h"
|
| 14 | #include "include/af_inet.h"
|
| 15 | #include "include/apparmor.h"
|
| 16 | #include "include/file.h"
|
| 17 | #include "include/label.h"
|
| 18 | #include "include/net.h"
|
| 19 | #include "include/path.h"
|
| 20 | #include "include/policy.h"
|
| 21 | #include "include/cred.h"
|
| 22 |
|
| 23 |
|
| 24 | static inline aa_state_t RULE_MEDIATES_SK(struct aa_ruleset *rules,
|
| 25 | const struct sock *sk)
|
| 26 | {
|
| 27 | return RULE_MEDIATES_NET(rules);
|
| 28 | }
|
| 29 |
|
| 30 |
|
| 31 | enum addr_type {
|
| 32 | ADDR_LOCAL = 0,
|
| 33 | ADDR_LOCAL_PRIV = 1,
|
| 34 | ADDR_REMOTE = 2,
|
| 35 | };
|
| 36 |
|
| 37 | struct match_addr {
|
| 38 | const char *addrp;
|
| 39 | enum addr_type addrtype;
|
| 40 | int len;
|
| 41 | __be16 port;
|
| 42 | };
|
| 43 |
|
| 44 | struct stored_match_addr {
|
| 45 | union {
|
| 46 | struct sockaddr addr;
|
| 47 | struct sockaddr_in addr4;
|
| 48 | struct sockaddr_in6 addr6;
|
| 49 | };
|
| 50 | int addrlen;
|
| 51 | struct match_addr maddr;
|
| 52 | };
|
| 53 |
|
| 54 | static void set_ad_create(struct apparmor_audit_data *ad,
|
| 55 | int family, int type, int protocol)
|
| 56 | {
|
| 57 | ad->common.u.net->family = family;
|
| 58 | ad->net.type = type;
|
| 59 | ad->net.protocol = protocol;
|
| 60 | }
|
| 61 |
|
| 62 | static int set_ad_addr(struct apparmor_audit_data *ad,
|
| 63 | u16 family, bool source, struct match_addr *maddr)
|
| 64 | {
|
| 65 | ad->common.u.net->family = family;
|
| 66 |
|
| 67 | if (source) {
|
| 68 | ad->common.u.net->sport = maddr->port;
|
| 69 | if (maddr->addrp) {
|
| 70 | if (family == AF_INET)
|
| 71 |
|
| 72 | ad->common.u.net->v4info.saddr = *(__be32 *)maddr->addrp;
|
| 73 | else
|
| 74 |
|
| 75 | ad->common.u.net->v6info.saddr = *(struct in6_addr *)maddr->addrp;
|
| 76 | }
|
| 77 | } else {
|
| 78 | ad->common.u.net->dport = maddr->port;
|
| 79 | if (maddr->addrp) {
|
| 80 | if (family == AF_INET)
|
| 81 |
|
| 82 | ad->common.u.net->v4info.daddr = *(__be32 *)maddr->addrp;
|
| 83 | else
|
| 84 |
|
| 85 | ad->common.u.net->v6info.daddr = *(struct in6_addr *)maddr->addrp;
|
| 86 | }
|
| 87 | }
|
| 88 | return 0;
|
| 89 | }
|
| 90 |
|
| 91 | |
| 92 | * raw_port - if set raw_port (protocol) when SOCK_RAW
|
| 93 | static int map_addr(struct sockaddr *addr, int addrlen, u16 raw_port,
|
| 94 | enum addr_type addrtype, struct match_addr *maddr,
|
| 95 | struct apparmor_audit_data *ad)
|
| 96 | {
|
| 97 | struct sockaddr_in *addr4 = NULL;
|
| 98 | struct sockaddr_in6 *addr6 = NULL;
|
| 99 |
|
| 100 | AA_BUG(!addr);
|
| 101 | AA_BUG(!maddr);
|
| 102 |
|
| 103 | maddr->addrtype = addrtype;
|
| 104 | if (!addr || addrlen < offsetofend(struct sockaddr, sa_family)) {
|
| 105 | maddr->addrp = NULL;
|
| 106 | maddr->port = 0;
|
| 107 | maddr->len = 0;
|
| 108 | return 0;
|
| 109 | }
|
| 110 |
|
| 111 | |
| 112 | * its possibly to have sk->sk_family == PF_INET6 and
|
| 113 | * addr->sa_family == AF_INET. sk_family is used for socket
|
| 114 | * mediation, sa_family for when we have address ...
|
| 115 |
|
| 116 | switch (addr->sa_family) {
|
| 117 | case AF_INET:
|
| 118 | addr4 = (struct sockaddr_in *)addr;
|
| 119 | if (addrlen < sizeof(struct sockaddr_in))
|
| 120 | return -EINVAL;
|
| 121 | maddr->port = addr4->sin_port;
|
| 122 | maddr->addrp = (char *)&addr4->sin_addr.s_addr;
|
| 123 | maddr->len = 4;
|
| 124 | break;
|
| 125 | case AF_INET6:
|
| 126 | addr6 = (struct sockaddr_in6 *)addr;
|
| 127 | if (addrlen < SIN6_LEN_RFC2133)
|
| 128 | return -EINVAL;
|
| 129 | maddr->port = addr6->sin6_port;
|
| 130 | maddr->addrp = (char *)&addr6->sin6_addr.s6_addr;
|
| 131 | maddr->len = 16;
|
| 132 | break;
|
| 133 | default:
|
| 134 | return -EAFNOSUPPORT;
|
| 135 | }
|
| 136 |
|
| 137 | if (raw_port && addrtype != ADDR_REMOTE)
|
| 138 | maddr->port = htons(raw_port);
|
| 139 | if (ad)
|
| 140 | set_ad_addr(ad, addr->sa_family, addrtype != ADDR_REMOTE, maddr);
|
| 141 |
|
| 142 | return 0;
|
| 143 | }
|
| 144 |
|
| 145 |
|
| 146 | static int map_sock_addr(struct socket *sock, enum addr_type addrtype,
|
| 147 | struct stored_match_addr *maddr,
|
| 148 | struct apparmor_audit_data *ad)
|
| 149 | {
|
| 150 |
|
| 151 | maddr->addrlen = sock->ops->getname(sock, (struct sockaddr *) &maddr->addr, addrtype != ADDR_REMOTE ? 0 : 1);
|
| 152 | if (maddr->addrlen == -ENOTCONN) {
|
| 153 | maddr->addrlen = 0;
|
| 154 | return map_addr(NULL, 0, 0, addrtype, &maddr->maddr, ad);
|
| 155 | } else if (maddr->addrlen < 0)
|
| 156 | return maddr->addrlen;
|
| 157 | return map_addr(&maddr->addr, maddr->addrlen, 0, addrtype,
|
| 158 | &maddr->maddr, ad);
|
| 159 | }
|
| 160 |
|
| 161 |
|
| 162 |
|
| 163 | static int bind_map_addr(const struct sock *sk, struct sockaddr *addr,
|
| 164 | int addrlen,
|
| 165 | struct match_addr *maddr,
|
| 166 | struct apparmor_audit_data *ad)
|
| 167 | {
|
| 168 | struct sockaddr_in *addr4 = NULL;
|
| 169 | struct sockaddr_in6 *addr6 = NULL;
|
| 170 | u16 family;
|
| 171 |
|
| 172 | AA_BUG(!sk);
|
| 173 | AA_BUG(!addr);
|
| 174 | AA_BUG(!maddr);
|
| 175 |
|
| 176 | if (addrlen < offsetofend(struct sockaddr, sa_family))
|
| 177 | return -EINVAL;
|
| 178 |
|
| 179 | maddr->addrtype = ADDR_LOCAL;
|
| 180 | |
| 181 | * its possibly to have sk->sk_family == PF_INET6 and
|
| 182 | * addr->sa_family == AF_INET. sk_family is used for socket
|
| 183 | * mediation, sa_family for when we have address ...
|
| 184 |
|
| 185 | family = addr->sa_family;
|
| 186 | switch (addr->sa_family) {
|
| 187 | case AF_UNSPEC:
|
| 188 | if (sk->sk_family == PF_INET6) {
|
| 189 |
|
| 190 | if (addrlen < SIN6_LEN_RFC2133)
|
| 191 | return -EINVAL;
|
| 192 |
|
| 193 | return -EAFNOSUPPORT;
|
| 194 | }
|
| 195 | |
| 196 | * AF_UNSPEC if the address is INADDR_ANY
|
| 197 |
|
| 198 | addr4 = (struct sockaddr_in *)addr;
|
| 199 | if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
|
| 200 | return -EAFNOSUPPORT;
|
| 201 | family = AF_INET;
|
| 202 | fallthrough;
|
| 203 | case AF_INET:
|
| 204 | addr4 = (struct sockaddr_in *)addr;
|
| 205 | if (addrlen < sizeof(struct sockaddr_in))
|
| 206 | return -EINVAL;
|
| 207 | maddr->port = addr4->sin_port;
|
| 208 | maddr->addrp = (char *)&addr4->sin_addr.s_addr;
|
| 209 | maddr->len = 4;
|
| 210 | break;
|
| 211 | case AF_INET6:
|
| 212 | addr6 = (struct sockaddr_in6 *)addr;
|
| 213 | if (addrlen < SIN6_LEN_RFC2133)
|
| 214 | return -EINVAL;
|
| 215 | maddr->port = addr6->sin6_port;
|
| 216 | maddr->addrp = (char *)&addr6->sin6_addr.s6_addr;
|
| 217 | maddr->len = 16;
|
| 218 | break;
|
| 219 | default:
|
| 220 | return -EAFNOSUPPORT;
|
| 221 | }
|
| 222 |
|
| 223 | if (ad)
|
| 224 | set_ad_addr(ad, family, true, maddr);
|
| 225 |
|
| 226 | return 0;
|
| 227 | }
|
| 228 |
|
| 229 |
|
| 230 | static inline int profile_sk_perm(struct aa_profile *profile, u32 request,
|
| 231 | const struct sock *sk,
|
| 232 | struct match_addr *maddr,
|
| 233 | struct apparmor_audit_data *ad)
|
| 234 | {
|
| 235 | AA_BUG(!profile);
|
| 236 | AA_BUG(!sk);
|
| 237 |
|
| 238 | return aa_profile_af_sk_perm(profile, ad, request, sk);
|
| 239 | }
|
| 240 |
|
| 241 |
|
| 242 | static int profile_create_perm(struct aa_profile *profile, int family,
|
| 243 | int type, int protocol,
|
| 244 | struct apparmor_audit_data *ad)
|
| 245 | {
|
| 246 | AA_BUG(!profile);
|
| 247 |
|
| 248 | return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type,
|
| 249 | protocol);
|
| 250 | }
|
| 251 |
|
| 252 |
|
| 253 |
|
| 254 | static int profile_remote_perm(struct aa_profile *profile,
|
| 255 | const struct sock *sk,
|
| 256 | u32 request, struct match_addr *raddr,
|
| 257 | struct match_addr *laddr,
|
| 258 | struct apparmor_audit_data *ad)
|
| 259 | {
|
| 260 | AA_BUG(!profile);
|
| 261 | AA_BUG(!sk);
|
| 262 | AA_BUG(!raddr);
|
| 263 | AA_BUG(!laddr);
|
| 264 | AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
| 265 | "family=%d", sk->sk_family);
|
| 266 |
|
| 267 | return aa_profile_af_sk_perm(profile, ad, request, sk);
|
| 268 | }
|
| 269 |
|
| 270 | static int profile_bind_perm(struct aa_profile *profile,
|
| 271 | const struct sock *sk,
|
| 272 | struct match_addr *maddr,
|
| 273 | struct apparmor_audit_data *ad)
|
| 274 | {
|
| 275 | return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk);
|
| 276 |
|
| 277 | }
|
| 278 |
|
| 279 | static int profile_listen_perm(struct aa_profile *profile,
|
| 280 | const struct sock *sk,
|
| 281 | struct match_addr *maddr, int backlog,
|
| 282 | struct apparmor_audit_data *ad)
|
| 283 | {
|
| 284 | AA_BUG(!profile);
|
| 285 | AA_BUG(!sk);
|
| 286 | AA_BUG(!maddr);
|
| 287 | AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
| 288 | "family=%d", sk->sk_family);
|
| 289 |
|
| 290 | return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk);
|
| 291 | }
|
| 292 |
|
| 293 | static inline int profile_accept_perm(struct aa_profile *profile,
|
| 294 | const struct sock *sk,
|
| 295 | struct match_addr *maddr,
|
| 296 | const struct sock *newsk,
|
| 297 | struct apparmor_audit_data *ad)
|
| 298 | {
|
| 299 | AA_BUG(!profile);
|
| 300 | AA_BUG(!sk);
|
| 301 |
|
| 302 | AA_BUG(!maddr);
|
| 303 | AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
| 304 | "family=%d", sk->sk_family);
|
| 305 |
|
| 306 | return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk);
|
| 307 | }
|
| 308 |
|
| 309 |
|
| 310 | static int profile_opt_perm(struct aa_profile *profile, u32 request,
|
| 311 | const struct sock *sk, struct match_addr *maddr,
|
| 312 | int level, int optname,
|
| 313 | struct apparmor_audit_data *ad)
|
| 314 | {
|
| 315 | AA_BUG(!profile);
|
| 316 | AA_BUG(!sk);
|
| 317 | AA_BUG(!maddr);
|
| 318 | AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
| 319 | "family=%d", sk->sk_family);
|
| 320 |
|
| 321 | return aa_profile_af_sk_perm(profile, ad, request, sk);
|
| 322 | }
|
| 323 |
|
| 324 |
|
| 325 |
|
| 326 | |
| 327 | |
| 328 |
|
| 329 |
|
| 330 | #define label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXX, YYYY, CALLBACKFN) \
|
| 331 | ({ \
|
| 332 | int __EERROR = 0; \
|
| 333 | if (label_mediates(LABEL, AA_CLASS_NET)) { \
|
| 334 | struct aa_profile *PROFILE; \
|
| 335 | DEFINE_AUDIT_SK(AAD, OP, CRED, SOCKSK); \
|
| 336 | (AAD).subj_cred = (CRED); \
|
| 337 | (AAD).request = (REQUEST); \
|
| 338 | __EERROR = (XXXX); \
|
| 339 | if (__EERROR == 0) { \
|
| 340 | __EERROR = (YYYY); \
|
| 341 | if (__EERROR == 0) { \
|
| 342 | __EERROR = fn_for_each(LABEL, PROFILE, \
|
| 343 | (CALLBACKFN)); \
|
| 344 | } \
|
| 345 | } \
|
| 346 | } \
|
| 347 | __EERROR; \
|
| 348 | })
|
| 349 |
|
| 350 |
|
| 351 | #define label_sk_has_perm(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, CALLBACKFN) \
|
| 352 | label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, \
|
| 353 | 0, 0, CALLBACKFN)
|
| 354 |
|
| 355 |
|
| 356 | #define label_sk_has_perm1(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXX, CALLBACKFN) \
|
| 357 | label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, \
|
| 358 | XXXX, 0, CALLBACKFN)
|
| 359 |
|
| 360 |
|
| 361 |
|
| 362 | #define sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, YYYYX, CALLBACKFN) \
|
| 363 | ({ \
|
| 364 | struct aa_label *__label; \
|
| 365 | struct aa_sk_ctx *__ctx = aa_sock(SOCKSK); \
|
| 366 | int __ERROR = 0; \
|
| 367 | bool __needput; \
|
| 368 | if (rcu_access_pointer(__ctx->label) != kernel_t) { \
|
| 369 | \
|
| 370 | __label = begin_current_label_crit_section(&__needput); \
|
| 371 | __ERROR = label_sk_has_perm2(current_cred(), __label, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, YYYYX, CALLBACKFN); \
|
| 372 | end_current_label_crit_section(__label, __needput); \
|
| 373 | } \
|
| 374 | __ERROR; \
|
| 375 | })
|
| 376 |
|
| 377 |
|
| 378 | #define sk_has_perm(SOCKSK, OP, REQUEST, PROFILE, AAD, CALLBACKFN) \
|
| 379 | sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, 0, 0, CALLBACKFN)
|
| 380 |
|
| 381 |
|
| 382 |
|
| 383 | #define sk_has_perm1(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, CALLBACKFN) \
|
| 384 | sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, 0, CALLBACKFN)
|
| 385 |
|
| 386 |
|
| 387 |
|
| 388 |
|
| 389 |
|
| 390 | int aa_inet_create_perm(struct aa_label *label, int family, int type,
|
| 391 | int protocol)
|
| 392 | {
|
| 393 | struct aa_profile *profile;
|
| 394 | int error = 0;
|
| 395 | DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family, type,
|
| 396 | protocol);
|
| 397 |
|
| 398 | ad.subj_cred = current_cred();
|
| 399 | set_ad_create(&ad, family, type, protocol);
|
| 400 | error = fn_for_each(label, profile,
|
| 401 | profile_create_perm(profile, family, type,
|
| 402 | protocol, &ad));
|
| 403 |
|
| 404 | return error;
|
| 405 | }
|
| 406 |
|
| 407 | int aa_inet_bind_perm(struct socket *sock, struct sockaddr *addr,
|
| 408 | int addrlen)
|
| 409 | {
|
| 410 | struct match_addr maddr;
|
| 411 |
|
| 412 | return sk_has_perm1(sock->sk, OP_BIND, AA_MAY_BIND, profile, ad,
|
| 413 | bind_map_addr(sock->sk, addr, addrlen, &maddr,
|
| 414 | &ad),
|
| 415 | profile_bind_perm(profile, sock->sk, &maddr, &ad));
|
| 416 | }
|
| 417 |
|
| 418 | int aa_inet_connect_perm(struct socket *sock, struct sockaddr *addr,
|
| 419 | int addrlen)
|
| 420 | {
|
| 421 | struct stored_match_addr laddr;
|
| 422 | struct match_addr raddr;
|
| 423 |
|
| 424 |
|
| 425 | if (addrlen < offsetofend(struct sockaddr, sa_family))
|
| 426 | return -EINVAL;
|
| 427 | if (addr->sa_family == AF_UNSPEC)
|
| 428 | return 0;
|
| 429 |
|
| 430 |
|
| 431 | return sk_has_perm2(sock->sk, OP_CONNECT, AA_MAY_CONNECT, profile, ad,
|
| 432 | map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
| 433 | map_addr(addr, addrlen, 0, ADDR_REMOTE, &raddr,
|
| 434 | &ad),
|
| 435 | profile_remote_perm(profile, sock->sk,
|
| 436 | AA_MAY_CONNECT, &raddr,
|
| 437 | &laddr.maddr, &ad));
|
| 438 | }
|
| 439 |
|
| 440 | int aa_inet_listen_perm(struct socket *sock, int backlog)
|
| 441 | {
|
| 442 | struct stored_match_addr maddr;
|
| 443 |
|
| 444 |
|
| 445 | return sk_has_perm1(sock->sk, OP_LISTEN, AA_MAY_LISTEN, profile, ad,
|
| 446 | map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
| 447 | profile_listen_perm(profile, sock->sk, &maddr.maddr,
|
| 448 | backlog, &ad));
|
| 449 | }
|
| 450 |
|
| 451 |
|
| 452 | int aa_inet_accept_perm(struct socket *sock, struct socket *newsock)
|
| 453 | {
|
| 454 | struct stored_match_addr maddr;
|
| 455 | int error;
|
| 456 |
|
| 457 | error = sk_has_perm1(sock->sk, OP_ACCEPT, AA_MAY_ACCEPT, profile, ad,
|
| 458 | map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
| 459 | profile_accept_perm(profile, sock->sk,
|
| 460 | &maddr.maddr,
|
| 461 | newsock->sk, &ad));
|
| 462 |
|
| 463 |
|
| 464 | return error;
|
| 465 | }
|
| 466 |
|
| 467 |
|
| 468 | int aa_inet_msg_perm(const char *op, u32 request, struct socket *sock,
|
| 469 | struct msghdr *msg, int size)
|
| 470 | {
|
| 471 | struct stored_match_addr laddr;
|
| 472 | struct match_addr raddr;
|
| 473 |
|
| 474 |
|
| 475 | return sk_has_perm2(sock->sk, op, request, profile, ad,
|
| 476 | map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
| 477 | map_addr(msg->msg_name, msg->msg_namelen, 0,
|
| 478 | ADDR_REMOTE, &raddr, &ad),
|
| 479 | profile_remote_perm(profile, sock->sk, request,
|
| 480 | &raddr, &laddr.maddr, &ad));
|
| 481 | }
|
| 482 |
|
| 483 |
|
| 484 | int aa_inet_opt_perm(const char *op, u32 request, struct socket *sock,
|
| 485 | int level, int optname)
|
| 486 | {
|
| 487 | struct stored_match_addr maddr;
|
| 488 |
|
| 489 | return sk_has_perm1(sock->sk, op, request, profile, ad,
|
| 490 | map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
| 491 | profile_opt_perm(profile, request, sock->sk,
|
| 492 | &maddr.maddr, level, optname, &ad));
|
| 493 | }
|
| 494 |
|
| 495 | static int inet_label_sock_perm(const struct cred *cred, struct aa_label *label,
|
| 496 | const char *op, u32 request,
|
| 497 | struct socket *sock)
|
| 498 | {
|
| 499 | struct stored_match_addr maddr;
|
| 500 |
|
| 501 | return label_sk_has_perm1(cred, label, sock->sk, op, request, profile,
|
| 502 | ad,
|
| 503 | map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
| 504 | profile_sk_perm(profile, request, sock->sk,
|
| 505 | &maddr.maddr, &ad));
|
| 506 | }
|
| 507 |
|
| 508 |
|
| 509 | int aa_inet_sock_perm(const char *op, u32 request, struct socket *sock)
|
| 510 | {
|
| 511 | struct aa_sk_ctx *ctx = aa_sock(sock->sk);
|
| 512 | struct aa_label *label;
|
| 513 | bool needput;
|
| 514 | int error;
|
| 515 |
|
| 516 | if (rcu_access_pointer(ctx->label) == kernel_t)
|
| 517 | return 0;
|
| 518 |
|
| 519 | label = begin_current_label_crit_section(&needput);
|
| 520 | error = inet_label_sock_perm(current_cred(), label, op, request, sock);
|
| 521 | end_current_label_crit_section(label, needput);
|
| 522 |
|
| 523 | return error;
|
| 524 | }
|
| 525 |
|
| 526 | int aa_inet_file_perm(const struct cred *subj_cred, struct aa_label *label,
|
| 527 | const char *op, u32 request, struct socket *sock)
|
| 528 | {
|
| 529 | u32 sk_req = request & ~NET_PEER_MASK;
|
| 530 | struct stored_match_addr laddr;
|
| 531 | const struct sock *sk = sock->sk;
|
| 532 | int error = 0;
|
| 533 |
|
| 534 | AA_BUG(!label);
|
| 535 | AA_BUG(!sock);
|
| 536 | AA_BUG(!sock->sk);
|
| 537 | AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
| 538 | "family=%d", sk->sk_family);
|
| 539 |
|
| 540 |
|
| 541 | error = label_sk_has_perm1(subj_cred, label, sock->sk, op, request,
|
| 542 | profile, ad,
|
| 543 | map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
| 544 | profile_sk_perm(profile, sk_req, sock->sk, &laddr.maddr,
|
| 545 | &ad));
|
| 546 |
|
| 547 | if (!error) {
|
| 548 | struct stored_match_addr raddr;
|
| 549 |
|
| 550 |
|
| 551 | error = map_sock_addr(sock, ADDR_REMOTE, &raddr, NULL);
|
| 552 | if (!error && raddr.maddr.addrp) {
|
| 553 | error = label_sk_has_perm1(subj_cred, label, sock->sk,
|
| 554 | op, request, profile, ad,
|
| 555 | set_ad_addr(&ad, raddr.addr.sa_family,
|
| 556 | false, &raddr.maddr),
|
| 557 | profile_remote_perm(profile, sock->sk,
|
| 558 | request,
|
| 559 | &raddr.maddr,
|
| 560 | &laddr.maddr, &ad));
|
| 561 | }
|
| 562 | }
|
| 563 |
|
| 564 | return error;
|
| 565 | }
|