0007-apparmor-compatibility-v2.x-net-rules.patch 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. From f153f512ed7a81e9b92a04d49869cffebf714f52 Mon Sep 17 00:00:00 2001
  2. From: John Johansen <[email protected]>
  3. Date: Sun, 17 Jun 2018 03:56:25 -0700
  4. Subject: UBUNTU: SAUCE: apparmor: patch to provide compatibility with v2.x net
  5. rules
  6. The networking rules upstreamed in 4.17 have a deliberate abi break
  7. with the older 2.x network rules.
  8. This patch provides compatibility with the older rules for those
  9. still using an apparmor 2.x userspace and still want network rules
  10. to work on a newer kernel.
  11. Signed-off-by: John Johansen <[email protected]>
  12. [ saf: resolve conflicts when rebasing to 4.20 ]
  13. Signed-off-by: Seth Forshee <[email protected]>
  14. ---
  15. security/apparmor/apparmorfs.c | 1 +
  16. security/apparmor/include/apparmor.h | 2 +-
  17. security/apparmor/include/net.h | 11 ++++++++
  18. security/apparmor/include/policy.h | 2 ++
  19. security/apparmor/net.c | 31 ++++++++++++++++-----
  20. security/apparmor/policy.c | 1 +
  21. security/apparmor/policy_unpack.c | 54 ++++++++++++++++++++++++++++++++++--
  22. 7 files changed, 92 insertions(+), 10 deletions(-)
  23. (limited to 'security/apparmor')
  24. diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
  25. index 2ee3b3d..0aef8e3 100644
  26. --- a/security/apparmor/apparmorfs.c
  27. +++ b/security/apparmor/apparmorfs.c
  28. @@ -2362,6 +2362,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
  29. AA_SFS_DIR("domain", aa_sfs_entry_domain),
  30. AA_SFS_DIR("file", aa_sfs_entry_file),
  31. AA_SFS_DIR("network_v8", aa_sfs_entry_network),
  32. + AA_SFS_DIR("network", aa_sfs_entry_network_compat),
  33. AA_SFS_DIR("mount", aa_sfs_entry_mount),
  34. AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
  35. AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
  36. diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
  37. index 1fbabdb..5870de2 100644
  38. --- a/security/apparmor/include/apparmor.h
  39. +++ b/security/apparmor/include/apparmor.h
  40. @@ -20,7 +20,7 @@
  41. #define AA_CLASS_UNKNOWN 1
  42. #define AA_CLASS_FILE 2
  43. #define AA_CLASS_CAP 3
  44. -#define AA_CLASS_DEPRECATED 4
  45. +#define AA_CLASS_NET_COMPAT 4
  46. #define AA_CLASS_RLIMITS 5
  47. #define AA_CLASS_DOMAIN 6
  48. #define AA_CLASS_MOUNT 7
  49. diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
  50. index aadb4b2..98a42ef 100644
  51. --- a/security/apparmor/include/net.h
  52. +++ b/security/apparmor/include/net.h
  53. @@ -68,6 +68,16 @@ struct aa_sk_ctx {
  54. DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
  55. (SK)->sk_protocol)
  56. +/* struct aa_net - network confinement data
  57. + * @allow: basic network families permissions
  58. + * @audit: which network permissions to force audit
  59. + * @quiet: which network permissions to quiet rejects
  60. + */
  61. +struct aa_net_compat {
  62. + u16 allow[AF_MAX];
  63. + u16 audit[AF_MAX];
  64. + u16 quiet[AF_MAX];
  65. +};
  66. #define af_select(FAMILY, FN, DEF_FN) \
  67. ({ \
  68. @@ -87,6 +97,7 @@ struct aa_secmark {
  69. };
  70. extern struct aa_sfs_entry aa_sfs_entry_network[];
  71. +extern struct aa_sfs_entry aa_sfs_entry_network_compat[];
  72. void audit_net_cb(struct audit_buffer *ab, void *va);
  73. int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
  74. diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
  75. index b5b4b81..f904105 100644
  76. --- a/security/apparmor/include/policy.h
  77. +++ b/security/apparmor/include/policy.h
  78. @@ -108,6 +108,7 @@ struct aa_data {
  79. * @policy: general match rules governing policy
  80. * @file: The set of rules governing basic file access and domain transitions
  81. * @caps: capabilities for the profile
  82. + * @net_compat: v2 compat network controls for the profile
  83. * @rlimits: rlimits for the profile
  84. *
  85. * @dents: dentries for the profiles file entries in apparmorfs
  86. @@ -145,6 +146,7 @@ struct aa_profile {
  87. struct aa_policydb policy;
  88. struct aa_file_rules file;
  89. struct aa_caps caps;
  90. + struct aa_net_compat *net_compat;
  91. int xattr_count;
  92. char **xattrs;
  93. diff --git a/security/apparmor/net.c b/security/apparmor/net.c
  94. index e0c1b50..e693df8 100644
  95. --- a/security/apparmor/net.c
  96. +++ b/security/apparmor/net.c
  97. @@ -24,6 +24,11 @@ struct aa_sfs_entry aa_sfs_entry_network[] = {
  98. { }
  99. };
  100. +struct aa_sfs_entry aa_sfs_entry_network_compat[] = {
  101. + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
  102. + { }
  103. +};
  104. +
  105. static const char * const net_mask_names[] = {
  106. "unknown",
  107. "send",
  108. @@ -118,14 +123,26 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
  109. if (profile_unconfined(profile))
  110. return 0;
  111. state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
  112. - if (!state)
  113. + if (state) {
  114. + if (!state)
  115. + return 0;
  116. + buffer[0] = cpu_to_be16(family);
  117. + buffer[1] = cpu_to_be16((u16) type);
  118. + state = aa_dfa_match_len(profile->policy.dfa, state,
  119. + (char *) &buffer, 4);
  120. + aa_compute_perms(profile->policy.dfa, state, &perms);
  121. + } else if (profile->net_compat) {
  122. + /* 2.x socket mediation compat */
  123. + perms.allow = (profile->net_compat->allow[family] & (1 << type)) ?
  124. + ALL_PERMS_MASK : 0;
  125. + perms.audit = (profile->net_compat->audit[family] & (1 << type)) ?
  126. + ALL_PERMS_MASK : 0;
  127. + perms.quiet = (profile->net_compat->quiet[family] & (1 << type)) ?
  128. + ALL_PERMS_MASK : 0;
  129. +
  130. + } else {
  131. return 0;
  132. -
  133. - buffer[0] = cpu_to_be16(family);
  134. - buffer[1] = cpu_to_be16((u16) type);
  135. - state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
  136. - 4);
  137. - aa_compute_perms(profile->policy.dfa, state, &perms);
  138. + }
  139. aa_apply_modes_to_perms(profile, &perms);
  140. return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
  141. diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
  142. index 4c010c9..a00e39b 100644
  143. --- a/security/apparmor/policy.c
  144. +++ b/security/apparmor/policy.c
  145. @@ -222,6 +222,7 @@ void aa_free_profile(struct aa_profile *profile)
  146. aa_free_file_rules(&profile->file);
  147. aa_free_cap_rules(&profile->caps);
  148. aa_free_rlimit_rules(&profile->rlimits);
  149. + kfree_sensitive(profile->net_compat);
  150. for (i = 0; i < profile->xattr_count; i++)
  151. kfree_sensitive(profile->xattrs[i]);
  152. diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
  153. index 4e1f96b..aedfecc 100644
  154. --- a/security/apparmor/policy_unpack.c
  155. +++ b/security/apparmor/policy_unpack.c
  156. @@ -34,7 +34,7 @@
  157. #define v5 5 /* base version */
  158. #define v6 6 /* per entry policydb mediation check */
  159. -#define v7 7
  160. +#define v7 7 /* v2 compat networking */
  161. #define v8 8 /* full network masking */
  162. /*
  163. @@ -314,6 +314,19 @@ fail:
  164. return false;
  165. }
  166. +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
  167. +{
  168. + if (unpack_nameX(e, AA_U16, name)) {
  169. + if (!inbounds(e, sizeof(u16)))
  170. + return 0;
  171. + if (data)
  172. + *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
  173. + e->pos += sizeof(u16);
  174. + return 1;
  175. + }
  176. + return 0;
  177. +}
  178. +
  179. static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
  180. {
  181. void *pos = e->pos;
  182. @@ -676,7 +689,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
  183. struct aa_profile *profile = NULL;
  184. const char *tmpname, *tmpns = NULL, *name = NULL;
  185. const char *info = "failed to unpack profile";
  186. - size_t ns_len;
  187. + size_t size = 0, ns_len;
  188. struct rhashtable_params params = { 0 };
  189. char *key = NULL;
  190. struct aa_data *data;
  191. @@ -823,6 +836,43 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
  192. goto fail;
  193. }
  194. + size = unpack_array(e, "net_allowed_af");
  195. + if (size || VERSION_LT(e->version, v8)) {
  196. + profile->net_compat = kzalloc(sizeof(struct aa_net_compat), GFP_KERNEL);
  197. + if (!profile->net_compat) {
  198. + info = "out of memory";
  199. + goto fail;
  200. + }
  201. + for (i = 0; i < size; i++) {
  202. + /* discard extraneous rules that this kernel will
  203. + * never request
  204. + */
  205. + if (i >= AF_MAX) {
  206. + u16 tmp;
  207. +
  208. + if (!unpack_u16(e, &tmp, NULL) ||
  209. + !unpack_u16(e, &tmp, NULL) ||
  210. + !unpack_u16(e, &tmp, NULL))
  211. + goto fail;
  212. + continue;
  213. + }
  214. + if (!unpack_u16(e, &profile->net_compat->allow[i], NULL))
  215. + goto fail;
  216. + if (!unpack_u16(e, &profile->net_compat->audit[i], NULL))
  217. + goto fail;
  218. + if (!unpack_u16(e, &profile->net_compat->quiet[i], NULL))
  219. + goto fail;
  220. + }
  221. + if (size && !unpack_nameX(e, AA_ARRAYEND, NULL))
  222. + goto fail;
  223. + if (VERSION_LT(e->version, v7)) {
  224. + /* pre v7 policy always allowed these */
  225. + profile->net_compat->allow[AF_UNIX] = 0xffff;
  226. + profile->net_compat->allow[AF_NETLINK] = 0xffff;
  227. + }
  228. + }
  229. +
  230. +
  231. if (unpack_nameX(e, AA_STRUCT, "policydb")) {
  232. /* generic policy dfa - optional and may be NULL */
  233. info = "failed to unpack policydb";