Skip to content

Commit 73688d1

Browse files
committed
apparmor: refactor prepare_ns() and make usable from different views
prepare_ns() will need to be called from alternate views, and namespaces will need to be created via different interfaces. So refactor and allow specifying the view ns. Signed-off-by: John Johansen <[email protected]>
1 parent 5fd1b95 commit 73688d1

File tree

5 files changed

+79
-38
lines changed

5 files changed

+79
-38
lines changed

security/apparmor/apparmorfs.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
125125

126126
error = PTR_ERR(data);
127127
if (!IS_ERR(data)) {
128-
error = aa_replace_profiles(data, size, PROF_ADD);
128+
error = aa_replace_profiles(__aa_current_profile()->ns, data,
129+
size, PROF_ADD);
129130
kvfree(data);
130131
}
131132

@@ -147,7 +148,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf,
147148
data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
148149
error = PTR_ERR(data);
149150
if (!IS_ERR(data)) {
150-
error = aa_replace_profiles(data, size, PROF_REPLACE);
151+
error = aa_replace_profiles(__aa_current_profile()->ns, data,
152+
size, PROF_REPLACE);
151153
kvfree(data);
152154
}
153155

security/apparmor/include/policy.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base,
184184
const char *fqname, size_t n);
185185
struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
186186

187-
ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace);
187+
ssize_t aa_replace_profiles(struct aa_ns *view, void *udata, size_t size,
188+
bool noreplace);
188189
ssize_t aa_remove_profiles(char *name, size_t size);
189190
void __aa_profile_list_release(struct list_head *head);
190191

security/apparmor/include/policy_ns.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ void aa_free_ns_kref(struct kref *kref);
8383

8484
struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name);
8585
struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n);
86-
struct aa_ns *aa_prepare_ns(const char *name);
86+
struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
87+
struct dentry *dir);
88+
struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name);
8789
void __aa_remove_ns(struct aa_ns *ns);
8890

8991
static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)

security/apparmor/policy.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
731731

732732
/**
733733
* aa_replace_profiles - replace profile(s) on the profile list
734+
* @view: namespace load is viewed from
734735
* @udata: serialized data stream (NOT NULL)
735736
* @size: size of the serialized data stream
736737
* @noreplace: true if only doing addition, no replacement allowed
@@ -741,7 +742,8 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname,
741742
*
742743
* Returns: size of data consumed else error code on failure.
743744
*/
744-
ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
745+
ssize_t aa_replace_profiles(struct aa_ns *view, void *udata, size_t size,
746+
bool noreplace)
745747
{
746748
const char *ns_name, *info = NULL;
747749
struct aa_ns *ns = NULL;
@@ -756,7 +758,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
756758
goto out;
757759

758760
/* released below */
759-
ns = aa_prepare_ns(ns_name);
761+
ns = aa_prepare_ns(view, ns_name);
760762
if (!ns) {
761763
error = audit_policy(op, GFP_KERNEL, ns_name,
762764
"failed to prepare namespace", -ENOMEM);

security/apparmor/policy_ns.c

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -181,48 +181,82 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name)
181181
return aa_findn_ns(root, name, strlen(name));
182182
}
183183

184+
static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
185+
struct dentry *dir)
186+
{
187+
struct aa_ns *ns;
188+
int error;
189+
190+
AA_BUG(!parent);
191+
AA_BUG(!name);
192+
AA_BUG(!mutex_is_locked(&parent->lock));
193+
194+
ns = alloc_ns(parent->base.hname, name);
195+
if (!ns)
196+
return NULL;
197+
mutex_lock(&ns->lock);
198+
error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name);
199+
if (error) {
200+
AA_ERROR("Failed to create interface for ns %s\n",
201+
ns->base.name);
202+
mutex_unlock(&ns->lock);
203+
aa_free_ns(ns);
204+
return ERR_PTR(error);
205+
}
206+
ns->parent = aa_get_ns(parent);
207+
list_add_rcu(&ns->base.list, &parent->sub_ns);
208+
/* add list ref */
209+
aa_get_ns(ns);
210+
mutex_unlock(&ns->lock);
211+
212+
return ns;
213+
}
214+
184215
/**
185-
* aa_prepare_ns - find an existing or create a new namespace of @name
186-
* @name: the namespace to find or add (MAYBE NULL)
216+
* aa_create_ns - create an ns, fail if it already exists
217+
* @parent: the parent of the namespace being created
218+
* @name: the name of the namespace
219+
* @dir: if not null the dir to put the ns entries in
187220
*
188-
* Returns: refcounted ns or NULL if failed to create one
221+
* Returns: the a refcounted ns that has been add or an ERR_PTR
189222
*/
190-
struct aa_ns *aa_prepare_ns(const char *name)
223+
struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
224+
struct dentry *dir)
191225
{
192-
struct aa_ns *ns, *root;
226+
struct aa_ns *ns;
193227

194-
root = aa_current_profile()->ns;
228+
AA_BUG(!mutex_is_locked(&parent->lock));
195229

196-
mutex_lock(&root->lock);
230+
/* try and find the specified ns */
231+
/* released by caller */
232+
ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
233+
if (!ns)
234+
ns = __aa_create_ns(parent, name, dir);
235+
else
236+
ns = ERR_PTR(-EEXIST);
197237

198-
/* if name isn't specified the profile is loaded to the current ns */
199-
if (!name) {
200-
/* released by caller */
201-
ns = aa_get_ns(root);
202-
goto out;
203-
}
238+
/* return ref */
239+
return ns;
240+
}
204241

242+
/**
243+
* aa_prepare_ns - find an existing or create a new namespace of @name
244+
* @parent: ns to treat as parent
245+
* @name: the namespace to find or add (NOT NULL)
246+
*
247+
* Returns: refcounted namespace or PTR_ERR if failed to create one
248+
*/
249+
struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name)
250+
{
251+
struct aa_ns *ns;
252+
253+
mutex_lock(&parent->lock);
205254
/* try and find the specified ns and if it doesn't exist create it */
206255
/* released by caller */
207-
ns = aa_get_ns(__aa_find_ns(&root->sub_ns, name));
208-
if (!ns) {
209-
ns = alloc_ns(root->base.hname, name);
210-
if (!ns)
211-
goto out;
212-
if (__aa_fs_ns_mkdir(ns, ns_subns_dir(root), name)) {
213-
AA_ERROR("Failed to create interface for ns %s\n",
214-
ns->base.name);
215-
aa_free_ns(ns);
216-
ns = NULL;
217-
goto out;
218-
}
219-
ns->parent = aa_get_ns(root);
220-
list_add_rcu(&ns->base.list, &root->sub_ns);
221-
/* add list ref */
222-
aa_get_ns(ns);
223-
}
224-
out:
225-
mutex_unlock(&root->lock);
256+
ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name));
257+
if (!ns)
258+
ns = __aa_create_ns(parent, name, NULL);
259+
mutex_unlock(&parent->lock);
226260

227261
/* return ref */
228262
return ns;

0 commit comments

Comments
 (0)