diff options
author | John Johansen <john.johansen@canonical.com> | 2010-07-23 05:52:40 -0700 |
---|---|---|
committer | Leann Ogasawara <leann.ogasawara@canonical.com> | 2010-09-02 13:47:09 -0700 |
commit | 8cb3e0f8ad669be1e2027cbafb58fa7cd1928f76 (patch) | |
tree | 928b07c9512b8443c7f66b8ed4f3c977449605a3 /security | |
parent | 0fa6552974fafc6cc4ffc3e1c5939b8eb2374443 (diff) |
UBUNTU: SAUCE: AppArmor 2.4 compatibility patch
Provide backward compatibility with previous versions of AppArmor user
space interface. This is needed for compatibility with 9.10 and 10.04 LTS
Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/Kconfig | 9 | ||||
-rw-r--r-- | security/apparmor/Makefile | 8 | ||||
-rw-r--r-- | security/apparmor/apparmorfs-24.c | 2 | ||||
-rw-r--r-- | security/apparmor/apparmorfs.c | 18 | ||||
-rw-r--r-- | security/apparmor/include/apparmorfs.h | 6 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 3 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 112 | ||||
-rw-r--r-- | security/apparmor/net.c | 8 | ||||
-rw-r--r-- | security/apparmor/policy.c | 1 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 39 |
10 files changed, 198 insertions, 8 deletions
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig index 72555b9ca7d..fdf3022d721 100644 --- a/security/apparmor/Kconfig +++ b/security/apparmor/Kconfig @@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE boot. If you are unsure how to answer this question, answer 1. + +config SECURITY_APPARMOR_COMPAT_24 + bool "Enable AppArmor 2.4 compatability" + depends on SECURITY_APPARMOR + default y + help + This option enables compatability with AppArmor 2.4. It is + recommended if compatability with older versions of AppArmor + is desired. diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile index f204869399e..e5e8968cb8b 100644 --- a/security/apparmor/Makefile +++ b/security/apparmor/Makefile @@ -4,17 +4,23 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ - resource.o sid.o file.o + resource.o sid.o file.o net.o + +apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o clean-files: capability_names.h af_names.h quiet_cmd_make-caps = GEN $@ cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ +quiet_cmd_make-af = GEN $@ +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ + quiet_cmd_make-rlim = GEN $@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@ $(obj)/capability.o : $(obj)/capability_names.h +$(obj)/net.o : $(obj)/af_names.h $(obj)/resource.o : $(obj)/rlim_names.h $(obj)/capability_names.h : $(srctree)/include/linux/capability.h $(call cmd,make-caps) diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c index 38b18d2c987..dc8c744ff28 100644 --- a/security/apparmor/apparmorfs-24.c +++ b/security/apparmor/apparmorfs-24.c @@ -243,7 +243,7 @@ static void p_stop(struct seq_file *f, void *p) } /** - * seq_show_profile - + * seq_show_profile - show a profile entry * @f: seq_file to file * @p: current position (profile) (NOT NULL) * diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 7320331b44a..0e2744926bb 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -182,7 +182,11 @@ void __init aa_destroy_aafs(void) aafs_remove(".remove"); aafs_remove(".replace"); aafs_remove(".load"); - +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 + aafs_remove("profiles"); + aafs_remove("matching"); + aafs_remove("features"); +#endif securityfs_remove(aa_fs_dentry); aa_fs_dentry = NULL; } @@ -213,7 +217,17 @@ int __init aa_create_aafs(void) aa_fs_dentry = NULL; goto error; } - +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 + error = aafs_create("matching", 0444, &aa_fs_matching_fops); + if (error) + goto error; + error = aafs_create("features", 0444, &aa_fs_features_fops); + if (error) + goto error; +#endif + error = aafs_create("profiles", 0440, &aa_fs_profiles_fops); + if (error) + goto error; error = aafs_create(".load", 0640, &aa_fs_profile_load); if (error) goto error; diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h index cb1e93a114d..14f955ca082 100644 --- a/security/apparmor/include/apparmorfs.h +++ b/security/apparmor/include/apparmorfs.h @@ -17,4 +17,10 @@ extern void __init aa_destroy_aafs(void); +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 +extern const struct file_operations aa_fs_matching_fops; +extern const struct file_operations aa_fs_features_fops; +extern const struct file_operations aa_fs_profiles_fops; +#endif + #endif /* __AA_APPARMORFS_H */ diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index aeda5cf5690..67769294ffb 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -27,6 +27,7 @@ #include "capability.h" #include "domain.h" #include "file.h" +#include "net.h" #include "resource.h" extern const char *profile_mode_names[]; @@ -145,6 +146,7 @@ struct aa_namespace { * @size: the memory consumed by this profiles rules * @file: The set of rules governing basic file access and domain transitions * @caps: capabilities for the profile + * @net: network controls for the profile * @rlimits: rlimits for the profile * * The AppArmor profile contains the basic confinement data. Each profile @@ -181,6 +183,7 @@ struct aa_profile { struct aa_file_rules file; struct aa_caps caps; + struct aa_net net; struct aa_rlimit rlimits; }; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 7daf0d52803..e8d0821220f 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -31,6 +31,7 @@ #include "include/context.h" #include "include/file.h" #include "include/ipc.h" +#include "include/net.h" #include "include/path.h" #include "include/policy.h" #include "include/procattr.h" @@ -620,6 +621,104 @@ static int apparmor_task_setrlimit(unsigned int resource, return error; } +static int apparmor_socket_create(int family, int type, int protocol, int kern) +{ + struct aa_profile *profile; + int error = 0; + + if (kern) + return 0; + + profile = __aa_current_profile(); + if (!unconfined(profile)) + error = aa_net_perm(OP_CREATE, profile, family, type, protocol, + NULL); + return error; +} + +static int apparmor_socket_bind(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_BIND, sk); +} + +static int apparmor_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_CONNECT, sk); +} + +static int apparmor_socket_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_LISTEN, sk); +} + +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_ACCEPT, sk); +} + +static int apparmor_socket_sendmsg(struct socket *sock, + struct msghdr *msg, int size) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SENDMSG, sk); +} + +static int apparmor_socket_recvmsg(struct socket *sock, + struct msghdr *msg, int size, int flags) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_RECVMSG, sk); +} + +static int apparmor_socket_getsockname(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETSOCKNAME, sk); +} + +static int apparmor_socket_getpeername(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETPEERNAME, sk); +} + +static int apparmor_socket_getsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETSOCKOPT, sk); +} + +static int apparmor_socket_setsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SETSOCKOPT, sk); +} + +static int apparmor_socket_shutdown(struct socket *sock, int how) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk); +} + static struct security_operations apparmor_ops = { .name = "apparmor", @@ -651,6 +750,19 @@ static struct security_operations apparmor_ops = { .getprocattr = apparmor_getprocattr, .setprocattr = apparmor_setprocattr, + .socket_create = apparmor_socket_create, + .socket_bind = apparmor_socket_bind, + .socket_connect = apparmor_socket_connect, + .socket_listen = apparmor_socket_listen, + .socket_accept = apparmor_socket_accept, + .socket_sendmsg = apparmor_socket_sendmsg, + .socket_recvmsg = apparmor_socket_recvmsg, + .socket_getsockname = apparmor_socket_getsockname, + .socket_getpeername = apparmor_socket_getpeername, + .socket_getsockopt = apparmor_socket_getsockopt, + .socket_setsockopt = apparmor_socket_setsockopt, + .socket_shutdown = apparmor_socket_shutdown, + .cred_alloc_blank = apparmor_cred_alloc_blank, .cred_free = apparmor_cred_free, .cred_prepare = apparmor_cred_prepare, diff --git a/security/apparmor/net.c b/security/apparmor/net.c index ea8408302d0..7c36e82da55 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -52,6 +52,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) } else { audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type); } + audit_log_format(ab, " protocol=%d", sa->aad.net.protocol); } @@ -74,8 +75,9 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, struct common_audit_data sa; if (sk) { COMMON_AUDIT_DATA_INIT(&sa, NET); - } else - COMMON_AUDIT_DATA_INIT_NONE(&sa); + } else { + COMMON_AUDIT_DATA_INIT(&sa, NONE); + } /* todo fill in socket addr info */ sa.aad.op = op, @@ -117,7 +119,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, * * Returns: %0 else error if permission denied */ -int aa_net_perm(int op, struct aa_profile *profile,u16 family, int type, +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type, int protocol, struct sock *sk) { u16 family_mask; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 3cdc1ad0787..e3020ed074f 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile) aa_free_file_rules(&profile->file); aa_free_cap_rules(&profile->caps); + aa_free_net_rules(&profile->net); aa_free_rlimit_rules(&profile->rlimits); aa_free_sid(profile->sid); diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index eb3700e9fd3..6b0637b7dc6 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -190,6 +190,19 @@ fail: return 0; } +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name) +{ + if (unpack_nameX(e, AA_U16, name)) { + if (!inbounds(e, sizeof(u16))) + return 0; + if (data) + *data = le16_to_cpu(get_unaligned((u16 *) e->pos)); + e->pos += sizeof(u16); + return 1; + } + return 0; +} + static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) { if (unpack_nameX(e, AA_U32, name)) { @@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e) { struct aa_profile *profile = NULL; const char *name = NULL; - int error = -EPROTO; + size_t size = 0; + int i, error = -EPROTO; kernel_cap_t tmpcap; u32 tmp; @@ -559,6 +573,29 @@ static struct aa_profile *unpack_profile(struct aa_ext *e) if (!unpack_rlimits(e, profile)) goto fail; + size = unpack_array(e, "net_allowed_af"); + if (size) { + if (size > AF_MAX) + goto fail; + + for (i = 0; i < size; i++) { + if (!unpack_u16(e, &profile->net.allow[i], NULL)) + goto fail; + if (!unpack_u16(e, &profile->net.audit[i], NULL)) + goto fail; + if (!unpack_u16(e, &profile->net.quiet[i], NULL)) + goto fail; + } + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) + goto fail; + /* + * allow unix domain and netlink sockets they are handled + * by IPC + */ + } + profile->net.allow[AF_UNIX] = 0xffff; + profile->net.allow[AF_NETLINK] = 0xffff; + /* get file rules */ profile->file.dfa = unpack_dfa(e); if (IS_ERR(profile->file.dfa)) { |