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

apparmor: add base infastructure for socket mediation

version 2 - Force an abi break. Network mediation will only be
available in v8 abi complaint policy.

Provide a basic mediation of sockets. This is not a full net mediation
but just whether a spcific family of socket can be used by an
application, along with setting up some basic infrastructure for
network mediation to follow.

the user space rule hav the basic form of
NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ]
[ TYPE | PROTOCOL ]

DOMAIN = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' |
'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' |
'netbeui' | 'security' | 'key' | 'packet' | 'ash' |
'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' |
'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' |
'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' |
'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' |
'vsock' | 'mpls' | 'ib' | 'kcm' ) ','

TYPE = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' |
'packet' )

PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )

eg.
network,
network inet,

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

+786 -8
+1
security/apparmor/.gitignore
··· 1 1 # 2 2 # Generated include files 3 3 # 4 + net_names.h 4 5 capability_names.h 5 6 rlim_names.h
+41 -2
security/apparmor/Makefile
··· 5 5 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 - resource.o secid.o file.o policy_ns.o label.o mount.o 8 + resource.o secid.o file.o policy_ns.o label.o mount.o net.o 9 9 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 10 10 11 - clean-files := capability_names.h rlim_names.h 11 + clean-files := capability_names.h rlim_names.h net_names.h 12 12 13 + # Build a lower case string table of address family names 14 + # Transform lines from 15 + # #define AF_LOCAL 1 /* POSIX name for AF_UNIX */ 16 + # #define AF_INET 2 /* Internet IP Protocol */ 17 + # to 18 + # [1] = "local", 19 + # [2] = "inet", 20 + # 21 + # and build the securityfs entries for the mapping. 22 + # Transforms lines from 23 + # #define AF_INET 2 /* Internet IP Protocol */ 24 + # to 25 + # #define AA_SFS_AF_MASK "local inet" 26 + quiet_cmd_make-af = GEN $@ 27 + cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\ 28 + sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ 29 + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ 30 + echo "};" >> $@ ;\ 31 + printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\ 32 + sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ 33 + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\ 34 + $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 35 + 36 + # Build a lower case string table of sock type names 37 + # Transform lines from 38 + # SOCK_STREAM = 1, 39 + # to 40 + # [1] = "stream", 41 + quiet_cmd_make-sock = GEN $@ 42 + cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\ 43 + sed $^ >>$@ -r -n \ 44 + -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ 45 + echo "};" >> $@ 13 46 14 47 # Build a lower case string table of capability names 15 48 # Transforms lines from ··· 95 62 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 96 63 97 64 $(obj)/capability.o : $(obj)/capability_names.h 65 + $(obj)/net.o : $(obj)/net_names.h 98 66 $(obj)/resource.o : $(obj)/rlim_names.h 99 67 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ 100 68 $(src)/Makefile ··· 103 69 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ 104 70 $(src)/Makefile 105 71 $(call cmd,make-rlim) 72 + $(obj)/net_names.h : $(srctree)/include/linux/socket.h \ 73 + $(srctree)/include/linux/net.h \ 74 + $(src)/Makefile 75 + $(call cmd,make-af) 76 + $(call cmd,make-sock)
+2
security/apparmor/apparmorfs.c
··· 2169 2169 AA_SFS_FILE_BOOLEAN("v5", 1), 2170 2170 AA_SFS_FILE_BOOLEAN("v6", 1), 2171 2171 AA_SFS_FILE_BOOLEAN("v7", 1), 2172 + AA_SFS_FILE_BOOLEAN("v8", 1), 2172 2173 { } 2173 2174 }; 2174 2175 ··· 2205 2204 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2206 2205 AA_SFS_DIR("domain", aa_sfs_entry_domain), 2207 2206 AA_SFS_DIR("file", aa_sfs_entry_file), 2207 + AA_SFS_DIR("network_v8", aa_sfs_entry_network), 2208 2208 AA_SFS_DIR("mount", aa_sfs_entry_mount), 2209 2209 AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 2210 2210 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
+30
security/apparmor/file.c
··· 21 21 #include "include/cred.h" 22 22 #include "include/file.h" 23 23 #include "include/match.h" 24 + #include "include/net.h" 24 25 #include "include/path.h" 25 26 #include "include/policy.h" 26 27 #include "include/label.h" ··· 561 560 return error; 562 561 } 563 562 563 + static int __file_sock_perm(const char *op, struct aa_label *label, 564 + struct aa_label *flabel, struct file *file, 565 + u32 request, u32 denied) 566 + { 567 + struct socket *sock = (struct socket *) file->private_data; 568 + int error; 569 + 570 + AA_BUG(!sock); 571 + 572 + /* revalidation due to label out of date. No revocation at this time */ 573 + if (!denied && aa_label_is_subset(flabel, label)) 574 + return 0; 575 + 576 + /* TODO: improve to skip profiles cached in flabel */ 577 + error = aa_sock_file_perm(label, op, request, sock); 578 + if (denied) { 579 + /* TODO: improve to skip profiles checked above */ 580 + /* check every profile in file label to is cached */ 581 + last_error(error, aa_sock_file_perm(flabel, op, request, sock)); 582 + } 583 + if (!error) 584 + update_file_ctx(file_ctx(file), label, request); 585 + 586 + return error; 587 + } 588 + 564 589 /** 565 590 * aa_file_perm - do permission revalidation check & audit for @file 566 591 * @op: operation being checked ··· 631 604 error = __file_path_perm(op, label, flabel, file, request, 632 605 denied); 633 606 607 + else if (S_ISSOCK(file_inode(file)->i_mode)) 608 + error = __file_sock_perm(op, label, flabel, file, request, 609 + denied); 634 610 done: 635 611 rcu_read_unlock(); 636 612
+2 -1
security/apparmor/include/apparmor.h
··· 24 24 #define AA_CLASS_UNKNOWN 1 25 25 #define AA_CLASS_FILE 2 26 26 #define AA_CLASS_CAP 3 27 - #define AA_CLASS_NET 4 27 + #define AA_CLASS_DEPRECATED 4 28 28 #define AA_CLASS_RLIMITS 5 29 29 #define AA_CLASS_DOMAIN 6 30 30 #define AA_CLASS_MOUNT 7 31 31 #define AA_CLASS_PTRACE 9 32 32 #define AA_CLASS_SIGNAL 10 33 + #define AA_CLASS_NET 14 33 34 #define AA_CLASS_LABEL 16 34 35 35 36 #define AA_CLASS_LAST AA_CLASS_LABEL
+6
security/apparmor/include/audit.h
··· 134 134 int signal; 135 135 int unmappedsig; 136 136 }; 137 + struct { 138 + int type, protocol; 139 + struct sock *peer_sk; 140 + void *addr; 141 + int addrlen; 142 + } net; 137 143 }; 138 144 }; 139 145 struct {
+106
security/apparmor/include/net.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor network mediation definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2017 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 + #ifndef __AA_NET_H 16 + #define __AA_NET_H 17 + 18 + #include <net/sock.h> 19 + #include <linux/path.h> 20 + 21 + #include "apparmorfs.h" 22 + #include "label.h" 23 + #include "perms.h" 24 + #include "policy.h" 25 + 26 + #define AA_MAY_SEND AA_MAY_WRITE 27 + #define AA_MAY_RECEIVE AA_MAY_READ 28 + 29 + #define AA_MAY_SHUTDOWN AA_MAY_DELETE 30 + 31 + #define AA_MAY_CONNECT AA_MAY_OPEN 32 + #define AA_MAY_ACCEPT 0x00100000 33 + 34 + #define AA_MAY_BIND 0x00200000 35 + #define AA_MAY_LISTEN 0x00400000 36 + 37 + #define AA_MAY_SETOPT 0x01000000 38 + #define AA_MAY_GETOPT 0x02000000 39 + 40 + #define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \ 41 + AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \ 42 + AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \ 43 + AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT) 44 + 45 + #define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \ 46 + AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\ 47 + AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \ 48 + AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \ 49 + AA_MAY_MPROT) 50 + 51 + #define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \ 52 + AA_MAY_ACCEPT) 53 + struct aa_sk_ctx { 54 + struct aa_label *label; 55 + struct aa_label *peer; 56 + }; 57 + 58 + #define SK_CTX(X) ((X)->sk_security) 59 + #define SOCK_ctx(X) SOCK_INODE(X)->i_security 60 + #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ 61 + struct lsm_network_audit NAME ## _net = { .sk = (SK), \ 62 + .family = (F)}; \ 63 + DEFINE_AUDIT_DATA(NAME, \ 64 + ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \ 65 + LSM_AUDIT_DATA_NONE, \ 66 + OP); \ 67 + NAME.u.net = &(NAME ## _net); \ 68 + aad(&NAME)->net.type = (T); \ 69 + aad(&NAME)->net.protocol = (P) 70 + 71 + #define DEFINE_AUDIT_SK(NAME, OP, SK) \ 72 + DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ 73 + (SK)->sk_protocol) 74 + 75 + 76 + #define af_select(FAMILY, FN, DEF_FN) \ 77 + ({ \ 78 + int __e; \ 79 + switch ((FAMILY)) { \ 80 + default: \ 81 + __e = DEF_FN; \ 82 + } \ 83 + __e; \ 84 + }) 85 + 86 + extern struct aa_sfs_entry aa_sfs_entry_network[]; 87 + 88 + void audit_net_cb(struct audit_buffer *ab, void *va); 89 + int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 90 + u32 request, u16 family, int type); 91 + int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 92 + int type, int protocol); 93 + static inline int aa_profile_af_sk_perm(struct aa_profile *profile, 94 + struct common_audit_data *sa, 95 + u32 request, 96 + struct sock *sk) 97 + { 98 + return aa_profile_af_perm(profile, sa, request, sk->sk_family, 99 + sk->sk_type); 100 + } 101 + int aa_sk_perm(const char *op, u32 request, struct sock *sk); 102 + 103 + int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 104 + struct socket *sock); 105 + 106 + #endif /* __AA_NET_H */
+3 -2
security/apparmor/include/perms.h
··· 138 138 139 139 140 140 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); 141 - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); 141 + void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 142 + u32 mask); 142 143 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 143 - u32 chrsmask, const char **names, u32 namesmask); 144 + u32 chrsmask, const char * const *names, u32 namesmask); 144 145 void aa_apply_modes_to_perms(struct aa_profile *profile, 145 146 struct aa_perms *perms); 146 147 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
+11
security/apparmor/include/policy.h
··· 30 30 #include "file.h" 31 31 #include "lib.h" 32 32 #include "label.h" 33 + #include "net.h" 33 34 #include "perms.h" 34 35 #include "resource.h" 35 36 ··· 223 222 return aa_dfa_match_len(profile->policy.dfa, 224 223 profile->policy.start[0], &class, 1); 225 224 return 0; 225 + } 226 + 227 + static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, 228 + u16 AF) { 229 + unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 230 + __be16 be_af = cpu_to_be16(AF); 231 + 232 + if (!state) 233 + return 0; 234 + return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); 226 235 } 227 236 228 237 /**
+3 -2
security/apparmor/lib.c
··· 211 211 *str = '\0'; 212 212 } 213 213 214 - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask) 214 + void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 215 + u32 mask) 215 216 { 216 217 const char *fmt = "%s"; 217 218 unsigned int i, perm = 1; ··· 230 229 } 231 230 232 231 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 233 - u32 chrsmask, const char **names, u32 namesmask) 232 + u32 chrsmask, const char * const *names, u32 namesmask) 234 233 { 235 234 char str[33]; 236 235
+392
security/apparmor/lsm.c
··· 33 33 #include "include/cred.h" 34 34 #include "include/file.h" 35 35 #include "include/ipc.h" 36 + #include "include/net.h" 36 37 #include "include/path.h" 37 38 #include "include/label.h" 38 39 #include "include/policy.h" ··· 744 743 return error; 745 744 } 746 745 746 + /** 747 + * apparmor_sk_alloc_security - allocate and attach the sk_security field 748 + */ 749 + static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) 750 + { 751 + struct aa_sk_ctx *ctx; 752 + 753 + ctx = kzalloc(sizeof(*ctx), flags); 754 + if (!ctx) 755 + return -ENOMEM; 756 + 757 + SK_CTX(sk) = ctx; 758 + 759 + return 0; 760 + } 761 + 762 + /** 763 + * apparmor_sk_free_security - free the sk_security field 764 + */ 765 + static void apparmor_sk_free_security(struct sock *sk) 766 + { 767 + struct aa_sk_ctx *ctx = SK_CTX(sk); 768 + 769 + SK_CTX(sk) = NULL; 770 + aa_put_label(ctx->label); 771 + aa_put_label(ctx->peer); 772 + kfree(ctx); 773 + } 774 + 775 + /** 776 + * apparmor_clone_security - clone the sk_security field 777 + */ 778 + static void apparmor_sk_clone_security(const struct sock *sk, 779 + struct sock *newsk) 780 + { 781 + struct aa_sk_ctx *ctx = SK_CTX(sk); 782 + struct aa_sk_ctx *new = SK_CTX(newsk); 783 + 784 + new->label = aa_get_label(ctx->label); 785 + new->peer = aa_get_label(ctx->peer); 786 + } 787 + 788 + /** 789 + * apparmor_socket_create - check perms before creating a new socket 790 + */ 791 + static int apparmor_socket_create(int family, int type, int protocol, int kern) 792 + { 793 + struct aa_label *label; 794 + int error = 0; 795 + 796 + AA_BUG(in_interrupt()); 797 + 798 + label = begin_current_label_crit_section(); 799 + if (!(kern || unconfined(label))) 800 + error = af_select(family, 801 + create_perm(label, family, type, protocol), 802 + aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, 803 + family, type, protocol)); 804 + end_current_label_crit_section(label); 805 + 806 + return error; 807 + } 808 + 809 + /** 810 + * apparmor_socket_post_create - setup the per-socket security struct 811 + * 812 + * Note: 813 + * - kernel sockets currently labeled unconfined but we may want to 814 + * move to a special kernel label 815 + * - socket may not have sk here if created with sock_create_lite or 816 + * sock_alloc. These should be accept cases which will be handled in 817 + * sock_graft. 818 + */ 819 + static int apparmor_socket_post_create(struct socket *sock, int family, 820 + int type, int protocol, int kern) 821 + { 822 + struct aa_label *label; 823 + 824 + if (kern) { 825 + struct aa_ns *ns = aa_get_current_ns(); 826 + 827 + label = aa_get_label(ns_unconfined(ns)); 828 + aa_put_ns(ns); 829 + } else 830 + label = aa_get_current_label(); 831 + 832 + if (sock->sk) { 833 + struct aa_sk_ctx *ctx = SK_CTX(sock->sk); 834 + 835 + aa_put_label(ctx->label); 836 + ctx->label = aa_get_label(label); 837 + } 838 + aa_put_label(label); 839 + 840 + return 0; 841 + } 842 + 843 + /** 844 + * apparmor_socket_bind - check perms before bind addr to socket 845 + */ 846 + static int apparmor_socket_bind(struct socket *sock, 847 + struct sockaddr *address, int addrlen) 848 + { 849 + AA_BUG(!sock); 850 + AA_BUG(!sock->sk); 851 + AA_BUG(!address); 852 + AA_BUG(in_interrupt()); 853 + 854 + return af_select(sock->sk->sk_family, 855 + bind_perm(sock, address, addrlen), 856 + aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk)); 857 + } 858 + 859 + /** 860 + * apparmor_socket_connect - check perms before connecting @sock to @address 861 + */ 862 + static int apparmor_socket_connect(struct socket *sock, 863 + struct sockaddr *address, int addrlen) 864 + { 865 + AA_BUG(!sock); 866 + AA_BUG(!sock->sk); 867 + AA_BUG(!address); 868 + AA_BUG(in_interrupt()); 869 + 870 + return af_select(sock->sk->sk_family, 871 + connect_perm(sock, address, addrlen), 872 + aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk)); 873 + } 874 + 875 + /** 876 + * apparmor_socket_list - check perms before allowing listen 877 + */ 878 + static int apparmor_socket_listen(struct socket *sock, int backlog) 879 + { 880 + AA_BUG(!sock); 881 + AA_BUG(!sock->sk); 882 + AA_BUG(in_interrupt()); 883 + 884 + return af_select(sock->sk->sk_family, 885 + listen_perm(sock, backlog), 886 + aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk)); 887 + } 888 + 889 + /** 890 + * apparmor_socket_accept - check perms before accepting a new connection. 891 + * 892 + * Note: while @newsock is created and has some information, the accept 893 + * has not been done. 894 + */ 895 + static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) 896 + { 897 + AA_BUG(!sock); 898 + AA_BUG(!sock->sk); 899 + AA_BUG(!newsock); 900 + AA_BUG(in_interrupt()); 901 + 902 + return af_select(sock->sk->sk_family, 903 + accept_perm(sock, newsock), 904 + aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk)); 905 + } 906 + 907 + static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock, 908 + struct msghdr *msg, int size) 909 + { 910 + AA_BUG(!sock); 911 + AA_BUG(!sock->sk); 912 + AA_BUG(!msg); 913 + AA_BUG(in_interrupt()); 914 + 915 + return af_select(sock->sk->sk_family, 916 + msg_perm(op, request, sock, msg, size), 917 + aa_sk_perm(op, request, sock->sk)); 918 + } 919 + 920 + /** 921 + * apparmor_socket_sendmsg - check perms before sending msg to another socket 922 + */ 923 + static int apparmor_socket_sendmsg(struct socket *sock, 924 + struct msghdr *msg, int size) 925 + { 926 + return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size); 927 + } 928 + 929 + /** 930 + * apparmor_socket_recvmsg - check perms before receiving a message 931 + */ 932 + static int apparmor_socket_recvmsg(struct socket *sock, 933 + struct msghdr *msg, int size, int flags) 934 + { 935 + return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size); 936 + } 937 + 938 + /* revaliation, get/set attr, shutdown */ 939 + static int aa_sock_perm(const char *op, u32 request, struct socket *sock) 940 + { 941 + AA_BUG(!sock); 942 + AA_BUG(!sock->sk); 943 + AA_BUG(in_interrupt()); 944 + 945 + return af_select(sock->sk->sk_family, 946 + sock_perm(op, request, sock), 947 + aa_sk_perm(op, request, sock->sk)); 948 + } 949 + 950 + /** 951 + * apparmor_socket_getsockname - check perms before getting the local address 952 + */ 953 + static int apparmor_socket_getsockname(struct socket *sock) 954 + { 955 + return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock); 956 + } 957 + 958 + /** 959 + * apparmor_socket_getpeername - check perms before getting remote address 960 + */ 961 + static int apparmor_socket_getpeername(struct socket *sock) 962 + { 963 + return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock); 964 + } 965 + 966 + /* revaliation, get/set attr, opt */ 967 + static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock, 968 + int level, int optname) 969 + { 970 + AA_BUG(!sock); 971 + AA_BUG(!sock->sk); 972 + AA_BUG(in_interrupt()); 973 + 974 + return af_select(sock->sk->sk_family, 975 + opt_perm(op, request, sock, level, optname), 976 + aa_sk_perm(op, request, sock->sk)); 977 + } 978 + 979 + /** 980 + * apparmor_getsockopt - check perms before getting socket options 981 + */ 982 + static int apparmor_socket_getsockopt(struct socket *sock, int level, 983 + int optname) 984 + { 985 + return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock, 986 + level, optname); 987 + } 988 + 989 + /** 990 + * apparmor_setsockopt - check perms before setting socket options 991 + */ 992 + static int apparmor_socket_setsockopt(struct socket *sock, int level, 993 + int optname) 994 + { 995 + return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock, 996 + level, optname); 997 + } 998 + 999 + /** 1000 + * apparmor_socket_shutdown - check perms before shutting down @sock conn 1001 + */ 1002 + static int apparmor_socket_shutdown(struct socket *sock, int how) 1003 + { 1004 + return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); 1005 + } 1006 + 1007 + /** 1008 + * apparmor_socket_sock_recv_skb - check perms before associating skb to sk 1009 + * 1010 + * Note: can not sleep may be called with locks held 1011 + * 1012 + * dont want protocol specific in __skb_recv_datagram() 1013 + * to deny an incoming connection socket_sock_rcv_skb() 1014 + */ 1015 + static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 1016 + { 1017 + return 0; 1018 + } 1019 + 1020 + 1021 + static struct aa_label *sk_peer_label(struct sock *sk) 1022 + { 1023 + struct aa_sk_ctx *ctx = SK_CTX(sk); 1024 + 1025 + if (ctx->peer) 1026 + return ctx->peer; 1027 + 1028 + return ERR_PTR(-ENOPROTOOPT); 1029 + } 1030 + 1031 + /** 1032 + * apparmor_socket_getpeersec_stream - get security context of peer 1033 + * 1034 + * Note: for tcp only valid if using ipsec or cipso on lan 1035 + */ 1036 + static int apparmor_socket_getpeersec_stream(struct socket *sock, 1037 + char __user *optval, 1038 + int __user *optlen, 1039 + unsigned int len) 1040 + { 1041 + char *name; 1042 + int slen, error = 0; 1043 + struct aa_label *label; 1044 + struct aa_label *peer; 1045 + 1046 + label = begin_current_label_crit_section(); 1047 + peer = sk_peer_label(sock->sk); 1048 + if (IS_ERR(peer)) { 1049 + error = PTR_ERR(peer); 1050 + goto done; 1051 + } 1052 + slen = aa_label_asxprint(&name, labels_ns(label), peer, 1053 + FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 1054 + FLAG_HIDDEN_UNCONFINED, GFP_KERNEL); 1055 + /* don't include terminating \0 in slen, it breaks some apps */ 1056 + if (slen < 0) { 1057 + error = -ENOMEM; 1058 + } else { 1059 + if (slen > len) { 1060 + error = -ERANGE; 1061 + } else if (copy_to_user(optval, name, slen)) { 1062 + error = -EFAULT; 1063 + goto out; 1064 + } 1065 + if (put_user(slen, optlen)) 1066 + error = -EFAULT; 1067 + out: 1068 + kfree(name); 1069 + 1070 + } 1071 + 1072 + done: 1073 + end_current_label_crit_section(label); 1074 + 1075 + return error; 1076 + } 1077 + 1078 + /** 1079 + * apparmor_socket_getpeersec_dgram - get security label of packet 1080 + * @sock: the peer socket 1081 + * @skb: packet data 1082 + * @secid: pointer to where to put the secid of the packet 1083 + * 1084 + * Sets the netlabel socket state on sk from parent 1085 + */ 1086 + static int apparmor_socket_getpeersec_dgram(struct socket *sock, 1087 + struct sk_buff *skb, u32 *secid) 1088 + 1089 + { 1090 + /* TODO: requires secid support */ 1091 + return -ENOPROTOOPT; 1092 + } 1093 + 1094 + /** 1095 + * apparmor_sock_graft - Initialize newly created socket 1096 + * @sk: child sock 1097 + * @parent: parent socket 1098 + * 1099 + * Note: could set off of SOCK_CTX(parent) but need to track inode and we can 1100 + * just set sk security information off of current creating process label 1101 + * Labeling of sk for accept case - probably should be sock based 1102 + * instead of task, because of the case where an implicitly labeled 1103 + * socket is shared by different tasks. 1104 + */ 1105 + static void apparmor_sock_graft(struct sock *sk, struct socket *parent) 1106 + { 1107 + struct aa_sk_ctx *ctx = SK_CTX(sk); 1108 + 1109 + if (!ctx->label) 1110 + ctx->label = aa_get_current_label(); 1111 + } 1112 + 747 1113 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 748 1114 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 749 1115 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), ··· 1144 776 1145 777 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1146 778 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 779 + 780 + LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), 781 + LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 782 + LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 783 + 784 + LSM_HOOK_INIT(socket_create, apparmor_socket_create), 785 + LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), 786 + LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), 787 + LSM_HOOK_INIT(socket_connect, apparmor_socket_connect), 788 + LSM_HOOK_INIT(socket_listen, apparmor_socket_listen), 789 + LSM_HOOK_INIT(socket_accept, apparmor_socket_accept), 790 + LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg), 791 + LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg), 792 + LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname), 793 + LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername), 794 + LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), 795 + LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), 796 + LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), 797 + LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), 798 + LSM_HOOK_INIT(socket_getpeersec_stream, 799 + apparmor_socket_getpeersec_stream), 800 + LSM_HOOK_INIT(socket_getpeersec_dgram, 801 + apparmor_socket_getpeersec_dgram), 802 + LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), 1147 803 1148 804 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 1149 805 LSM_HOOK_INIT(cred_free, apparmor_cred_free),
+187
security/apparmor/net.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor network mediation 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2017 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 "include/apparmor.h" 16 + #include "include/audit.h" 17 + #include "include/cred.h" 18 + #include "include/label.h" 19 + #include "include/net.h" 20 + #include "include/policy.h" 21 + 22 + #include "net_names.h" 23 + 24 + 25 + struct aa_sfs_entry aa_sfs_entry_network[] = { 26 + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 27 + { } 28 + }; 29 + 30 + static const char * const net_mask_names[] = { 31 + "unknown", 32 + "send", 33 + "receive", 34 + "unknown", 35 + 36 + "create", 37 + "shutdown", 38 + "connect", 39 + "unknown", 40 + 41 + "setattr", 42 + "getattr", 43 + "setcred", 44 + "getcred", 45 + 46 + "chmod", 47 + "chown", 48 + "chgrp", 49 + "lock", 50 + 51 + "mmap", 52 + "mprot", 53 + "unknown", 54 + "unknown", 55 + 56 + "accept", 57 + "bind", 58 + "listen", 59 + "unknown", 60 + 61 + "setopt", 62 + "getopt", 63 + "unknown", 64 + "unknown", 65 + 66 + "unknown", 67 + "unknown", 68 + "unknown", 69 + "unknown", 70 + }; 71 + 72 + 73 + /* audit callback for net specific fields */ 74 + void audit_net_cb(struct audit_buffer *ab, void *va) 75 + { 76 + struct common_audit_data *sa = va; 77 + 78 + audit_log_format(ab, " family="); 79 + if (address_family_names[sa->u.net->family]) 80 + audit_log_string(ab, address_family_names[sa->u.net->family]); 81 + else 82 + audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family); 83 + audit_log_format(ab, " sock_type="); 84 + if (sock_type_names[aad(sa)->net.type]) 85 + audit_log_string(ab, sock_type_names[aad(sa)->net.type]); 86 + else 87 + audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type); 88 + audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); 89 + 90 + if (aad(sa)->request & NET_PERMS_MASK) { 91 + audit_log_format(ab, " requested_mask="); 92 + aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0, 93 + net_mask_names, NET_PERMS_MASK); 94 + 95 + if (aad(sa)->denied & NET_PERMS_MASK) { 96 + audit_log_format(ab, " denied_mask="); 97 + aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0, 98 + net_mask_names, NET_PERMS_MASK); 99 + } 100 + } 101 + if (aad(sa)->peer) { 102 + audit_log_format(ab, " peer="); 103 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 104 + FLAGS_NONE, GFP_ATOMIC); 105 + } 106 + } 107 + 108 + /* Generic af perm */ 109 + int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 110 + u32 request, u16 family, int type) 111 + { 112 + struct aa_perms perms = { }; 113 + unsigned int state; 114 + __be16 buffer[2]; 115 + 116 + AA_BUG(family >= AF_MAX); 117 + AA_BUG(type < 0 || type >= SOCK_MAX); 118 + 119 + if (profile_unconfined(profile)) 120 + return 0; 121 + state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 122 + if (!state) 123 + return 0; 124 + 125 + buffer[0] = cpu_to_be16(family); 126 + buffer[1] = cpu_to_be16((u16) type); 127 + state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer, 128 + 4); 129 + aa_compute_perms(profile->policy.dfa, state, &perms); 130 + aa_apply_modes_to_perms(profile, &perms); 131 + 132 + return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 133 + } 134 + 135 + int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 136 + int type, int protocol) 137 + { 138 + struct aa_profile *profile; 139 + DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol); 140 + 141 + return fn_for_each_confined(label, profile, 142 + aa_profile_af_perm(profile, &sa, request, family, 143 + type)); 144 + } 145 + 146 + static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, 147 + struct sock *sk) 148 + { 149 + struct aa_profile *profile; 150 + DEFINE_AUDIT_SK(sa, op, sk); 151 + 152 + AA_BUG(!label); 153 + AA_BUG(!sk); 154 + 155 + if (unconfined(label)) 156 + return 0; 157 + 158 + return fn_for_each_confined(label, profile, 159 + aa_profile_af_sk_perm(profile, &sa, request, sk)); 160 + } 161 + 162 + int aa_sk_perm(const char *op, u32 request, struct sock *sk) 163 + { 164 + struct aa_label *label; 165 + int error; 166 + 167 + AA_BUG(!sk); 168 + AA_BUG(in_interrupt()); 169 + 170 + /* TODO: switch to begin_current_label ???? */ 171 + label = begin_current_label_crit_section(); 172 + error = aa_label_sk_perm(label, op, request, sk); 173 + end_current_label_crit_section(label); 174 + 175 + return error; 176 + } 177 + 178 + 179 + int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 180 + struct socket *sock) 181 + { 182 + AA_BUG(!label); 183 + AA_BUG(!sock); 184 + AA_BUG(!sock->sk); 185 + 186 + return aa_label_sk_perm(label, op, request, sock->sk); 187 + }
+2 -1
security/apparmor/policy_unpack.c
··· 37 37 38 38 #define v5 5 /* base version */ 39 39 #define v6 6 /* per entry policydb mediation check */ 40 - #define v7 7 /* full network masking */ 40 + #define v7 7 41 + #define v8 8 /* full network masking */ 41 42 42 43 /* 43 44 * The AppArmor interface treats data as a type byte followed by the