diff options
author | John Johansen <john.johansen@canonical.com> | 2017-06-02 20:44:27 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-10 20:11:32 -0400 |
commit | 3664268f19ea07bec55df92fe53ff9ed28968bcc (patch) | |
tree | 3db852e790109e4fbf27e7f91c6e0e642371c927 | |
parent | ae3b31653691b9c5b572b99596de3dfcc8f05006 (diff) |
apparmor: add namespace lookup fns()
Currently lookups are restricted to a single ns component in the
path. However when namespaces are allowed to have separate views, and
scopes this will not be sufficient, as it will be possible to have
a multiple component ns path in scope.
Add some ns lookup fns() to allow this and use them.
Signed-off-by: John Johansen <john.johansen@canonical.com>
-rw-r--r-- | security/apparmor/include/policy_ns.h | 13 | ||||
-rw-r--r-- | security/apparmor/policy.c | 10 | ||||
-rw-r--r-- | security/apparmor/policy_ns.c | 54 |
3 files changed, 73 insertions, 4 deletions
diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h index 23e7cb770226..2f7e480a34e0 100644 --- a/security/apparmor/include/policy_ns.h +++ b/security/apparmor/include/policy_ns.h | |||
@@ -89,6 +89,8 @@ void aa_free_ns_kref(struct kref *kref); | |||
89 | 89 | ||
90 | struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name); | 90 | struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name); |
91 | struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n); | 91 | struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n); |
92 | struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n); | ||
93 | struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n); | ||
92 | struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, | 94 | struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, |
93 | struct dentry *dir); | 95 | struct dentry *dir); |
94 | struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name); | 96 | struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name); |
@@ -148,4 +150,15 @@ static inline struct aa_ns *__aa_find_ns(struct list_head *head, | |||
148 | return __aa_findn_ns(head, name, strlen(name)); | 150 | return __aa_findn_ns(head, name, strlen(name)); |
149 | } | 151 | } |
150 | 152 | ||
153 | static inline struct aa_ns *__aa_lookup_ns(struct aa_ns *base, | ||
154 | const char *hname) | ||
155 | { | ||
156 | return __aa_lookupn_ns(base, hname, strlen(hname)); | ||
157 | } | ||
158 | |||
159 | static inline struct aa_ns *aa_lookup_ns(struct aa_ns *view, const char *name) | ||
160 | { | ||
161 | return aa_lookupn_ns(view, name, strlen(name)); | ||
162 | } | ||
163 | |||
151 | #endif /* AA_NAMESPACE_H */ | 164 | #endif /* AA_NAMESPACE_H */ |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 0a99e5324da0..d95aae6bf710 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -566,7 +566,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, | |||
566 | 566 | ||
567 | name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len); | 567 | name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len); |
568 | if (ns_name) { | 568 | if (ns_name) { |
569 | ns = aa_findn_ns(base->ns, ns_name, ns_len); | 569 | ns = aa_lookupn_ns(base->ns, ns_name, ns_len); |
570 | if (!ns) | 570 | if (!ns) |
571 | return NULL; | 571 | return NULL; |
572 | } else | 572 | } else |
@@ -1108,7 +1108,7 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, | |||
1108 | struct aa_ns *root = NULL, *ns = NULL; | 1108 | struct aa_ns *root = NULL, *ns = NULL; |
1109 | struct aa_profile *profile = NULL; | 1109 | struct aa_profile *profile = NULL; |
1110 | const char *name = fqname, *info = NULL; | 1110 | const char *name = fqname, *info = NULL; |
1111 | char *ns_name = NULL; | 1111 | const char *ns_name = NULL; |
1112 | ssize_t error = 0; | 1112 | ssize_t error = 0; |
1113 | 1113 | ||
1114 | if (*fqname == 0) { | 1114 | if (*fqname == 0) { |
@@ -1120,9 +1120,11 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, | |||
1120 | root = view; | 1120 | root = view; |
1121 | 1121 | ||
1122 | if (fqname[0] == ':') { | 1122 | if (fqname[0] == ':') { |
1123 | name = aa_split_fqname(fqname, &ns_name); | 1123 | size_t ns_len; |
1124 | |||
1125 | name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len); | ||
1124 | /* released below */ | 1126 | /* released below */ |
1125 | ns = aa_find_ns(root, ns_name); | 1127 | ns = aa_lookupn_ns(root, ns_name, ns_len); |
1126 | if (!ns) { | 1128 | if (!ns) { |
1127 | info = "namespace does not exist"; | 1129 | info = "namespace does not exist"; |
1128 | error = -ENOENT; | 1130 | error = -ENOENT; |
diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c index f3418a9e59b1..c05316809a5e 100644 --- a/security/apparmor/policy_ns.c +++ b/security/apparmor/policy_ns.c | |||
@@ -183,6 +183,60 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) | |||
183 | return aa_findn_ns(root, name, strlen(name)); | 183 | return aa_findn_ns(root, name, strlen(name)); |
184 | } | 184 | } |
185 | 185 | ||
186 | /** | ||
187 | * __aa_lookupn_ns - lookup the namespace matching @hname | ||
188 | * @base: base list to start looking up profile name from (NOT NULL) | ||
189 | * @hname: hierarchical ns name (NOT NULL) | ||
190 | * @n: length of @hname | ||
191 | * | ||
192 | * Requires: rcu_read_lock be held | ||
193 | * | ||
194 | * Returns: unrefcounted ns pointer or NULL if not found | ||
195 | * | ||
196 | * Do a relative name lookup, recursing through profile tree. | ||
197 | */ | ||
198 | struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n) | ||
199 | { | ||
200 | struct aa_ns *ns = view; | ||
201 | const char *split; | ||
202 | |||
203 | for (split = strnstr(hname, "//", n); split; | ||
204 | split = strnstr(hname, "//", n)) { | ||
205 | ns = __aa_findn_ns(&ns->sub_ns, hname, split - hname); | ||
206 | if (!ns) | ||
207 | return NULL; | ||
208 | |||
209 | n -= split + 2 - hname; | ||
210 | hname = split + 2; | ||
211 | } | ||
212 | |||
213 | if (n) | ||
214 | return __aa_findn_ns(&ns->sub_ns, hname, n); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * aa_lookupn_ns - look up a policy namespace relative to @view | ||
220 | * @view: namespace to search in (NOT NULL) | ||
221 | * @name: name of namespace to find (NOT NULL) | ||
222 | * @n: length of @name | ||
223 | * | ||
224 | * Returns: a refcounted namespace on the list, or NULL if no namespace | ||
225 | * called @name exists. | ||
226 | * | ||
227 | * refcount released by caller | ||
228 | */ | ||
229 | struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n) | ||
230 | { | ||
231 | struct aa_ns *ns = NULL; | ||
232 | |||
233 | rcu_read_lock(); | ||
234 | ns = aa_get_ns(__aa_lookupn_ns(view, name, n)); | ||
235 | rcu_read_unlock(); | ||
236 | |||
237 | return ns; | ||
238 | } | ||
239 | |||
186 | static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, | 240 | static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, |
187 | struct dentry *dir) | 241 | struct dentry *dir) |
188 | { | 242 | { |