Commit 0d259f043f5f60f74c4fd020aac190cb6450e918

Authored by John Johansen
1 parent 038165070a

apparmor: add interface files for profiles and namespaces

Add basic interface files to access namespace and profile information.
The interface files are created when a profile is loaded and removed
when the profile or namespace is removed.

Signed-off-by: John Johansen <john.johansen@canonical.com>

Showing 7 changed files with 436 additions and 29 deletions Side-by-side Diff

security/apparmor/apparmorfs.c
... ... @@ -12,6 +12,7 @@
12 12 * License.
13 13 */
14 14  
  15 +#include <linux/ctype.h>
15 16 #include <linux/security.h>
16 17 #include <linux/vmalloc.h>
17 18 #include <linux/module.h>
... ... @@ -28,6 +29,45 @@
28 29 #include "include/resource.h"
29 30  
30 31 /**
  32 + * aa_mangle_name - mangle a profile name to std profile layout form
  33 + * @name: profile name to mangle (NOT NULL)
  34 + * @target: buffer to store mangled name, same length as @name (MAYBE NULL)
  35 + *
  36 + * Returns: length of mangled name
  37 + */
  38 +static int mangle_name(char *name, char *target)
  39 +{
  40 + char *t = target;
  41 +
  42 + while (*name == '/' || *name == '.')
  43 + name++;
  44 +
  45 + if (target) {
  46 + for (; *name; name++) {
  47 + if (*name == '/')
  48 + *(t)++ = '.';
  49 + else if (isspace(*name))
  50 + *(t)++ = '_';
  51 + else if (isalnum(*name) || strchr("._-", *name))
  52 + *(t)++ = *name;
  53 + }
  54 +
  55 + *t = 0;
  56 + } else {
  57 + int len = 0;
  58 + for (; *name; name++) {
  59 + if (isalnum(*name) || isspace(*name) ||
  60 + strchr("/._-", *name))
  61 + len++;
  62 + }
  63 +
  64 + return len;
  65 + }
  66 +
  67 + return t - target;
  68 +}
  69 +
  70 +/**
31 71 * aa_simple_write_to_buffer - common routine for getting policy from user
32 72 * @op: operation doing the user buffer copy
33 73 * @userbuf: user buffer to copy data from (NOT NULL)
34 74  
... ... @@ -182,8 +222,263 @@
182 222 .release = single_release,
183 223 };
184 224  
185   -/** Base file system setup **/
  225 +static int aa_fs_seq_profile_open(struct inode *inode, struct file *file,
  226 + int (*show)(struct seq_file *, void *))
  227 +{
  228 + struct aa_replacedby *r = aa_get_replacedby(inode->i_private);
  229 + int error = single_open(file, show, r);
186 230  
  231 + if (error) {
  232 + file->private_data = NULL;
  233 + aa_put_replacedby(r);
  234 + }
  235 +
  236 + return error;
  237 +}
  238 +
  239 +static int aa_fs_seq_profile_release(struct inode *inode, struct file *file)
  240 +{
  241 + struct seq_file *seq = (struct seq_file *) file->private_data;
  242 + if (seq)
  243 + aa_put_replacedby(seq->private);
  244 + return single_release(inode, file);
  245 +}
  246 +
  247 +static int aa_fs_seq_profname_show(struct seq_file *seq, void *v)
  248 +{
  249 + struct aa_replacedby *r = seq->private;
  250 + struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
  251 + seq_printf(seq, "%s\n", profile->base.name);
  252 + aa_put_profile(profile);
  253 +
  254 + return 0;
  255 +}
  256 +
  257 +static int aa_fs_seq_profname_open(struct inode *inode, struct file *file)
  258 +{
  259 + return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profname_show);
  260 +}
  261 +
  262 +static const struct file_operations aa_fs_profname_fops = {
  263 + .owner = THIS_MODULE,
  264 + .open = aa_fs_seq_profname_open,
  265 + .read = seq_read,
  266 + .llseek = seq_lseek,
  267 + .release = aa_fs_seq_profile_release,
  268 +};
  269 +
  270 +static int aa_fs_seq_profmode_show(struct seq_file *seq, void *v)
  271 +{
  272 + struct aa_replacedby *r = seq->private;
  273 + struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
  274 + seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
  275 + aa_put_profile(profile);
  276 +
  277 + return 0;
  278 +}
  279 +
  280 +static int aa_fs_seq_profmode_open(struct inode *inode, struct file *file)
  281 +{
  282 + return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profmode_show);
  283 +}
  284 +
  285 +static const struct file_operations aa_fs_profmode_fops = {
  286 + .owner = THIS_MODULE,
  287 + .open = aa_fs_seq_profmode_open,
  288 + .read = seq_read,
  289 + .llseek = seq_lseek,
  290 + .release = aa_fs_seq_profile_release,
  291 +};
  292 +
  293 +/** fns to setup dynamic per profile/namespace files **/
  294 +void __aa_fs_profile_rmdir(struct aa_profile *profile)
  295 +{
  296 + struct aa_profile *child;
  297 + int i;
  298 +
  299 + if (!profile)
  300 + return;
  301 +
  302 + list_for_each_entry(child, &profile->base.profiles, base.list)
  303 + __aa_fs_profile_rmdir(child);
  304 +
  305 + for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
  306 + struct aa_replacedby *r;
  307 + if (!profile->dents[i])
  308 + continue;
  309 +
  310 + r = profile->dents[i]->d_inode->i_private;
  311 + securityfs_remove(profile->dents[i]);
  312 + aa_put_replacedby(r);
  313 + profile->dents[i] = NULL;
  314 + }
  315 +}
  316 +
  317 +void __aa_fs_profile_migrate_dents(struct aa_profile *old,
  318 + struct aa_profile *new)
  319 +{
  320 + int i;
  321 +
  322 + for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
  323 + new->dents[i] = old->dents[i];
  324 + old->dents[i] = NULL;
  325 + }
  326 +}
  327 +
  328 +static struct dentry *create_profile_file(struct dentry *dir, const char *name,
  329 + struct aa_profile *profile,
  330 + const struct file_operations *fops)
  331 +{
  332 + struct aa_replacedby *r = aa_get_replacedby(profile->replacedby);
  333 + struct dentry *dent;
  334 +
  335 + dent = securityfs_create_file(name, S_IFREG | 0444, dir, r, fops);
  336 + if (IS_ERR(dent))
  337 + aa_put_replacedby(r);
  338 +
  339 + return dent;
  340 +}
  341 +
  342 +/* requires lock be held */
  343 +int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
  344 +{
  345 + struct aa_profile *child;
  346 + struct dentry *dent = NULL, *dir;
  347 + int error;
  348 +
  349 + if (!parent) {
  350 + struct aa_profile *p;
  351 + p = aa_deref_parent(profile);
  352 + dent = prof_dir(p);
  353 + /* adding to parent that previously didn't have children */
  354 + dent = securityfs_create_dir("profiles", dent);
  355 + if (IS_ERR(dent))
  356 + goto fail;
  357 + prof_child_dir(p) = parent = dent;
  358 + }
  359 +
  360 + if (!profile->dirname) {
  361 + int len, id_len;
  362 + len = mangle_name(profile->base.name, NULL);
  363 + id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id);
  364 +
  365 + profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL);
  366 + if (!profile->dirname)
  367 + goto fail;
  368 +
  369 + mangle_name(profile->base.name, profile->dirname);
  370 + sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++);
  371 + }
  372 +
  373 + dent = securityfs_create_dir(profile->dirname, parent);
  374 + if (IS_ERR(dent))
  375 + goto fail;
  376 + prof_dir(profile) = dir = dent;
  377 +
  378 + dent = create_profile_file(dir, "name", profile, &aa_fs_profname_fops);
  379 + if (IS_ERR(dent))
  380 + goto fail;
  381 + profile->dents[AAFS_PROF_NAME] = dent;
  382 +
  383 + dent = create_profile_file(dir, "mode", profile, &aa_fs_profmode_fops);
  384 + if (IS_ERR(dent))
  385 + goto fail;
  386 + profile->dents[AAFS_PROF_MODE] = dent;
  387 +
  388 + list_for_each_entry(child, &profile->base.profiles, base.list) {
  389 + error = __aa_fs_profile_mkdir(child, prof_child_dir(profile));
  390 + if (error)
  391 + goto fail2;
  392 + }
  393 +
  394 + return 0;
  395 +
  396 +fail:
  397 + error = PTR_ERR(dent);
  398 +
  399 +fail2:
  400 + __aa_fs_profile_rmdir(profile);
  401 +
  402 + return error;
  403 +}
  404 +
  405 +void __aa_fs_namespace_rmdir(struct aa_namespace *ns)
  406 +{
  407 + struct aa_namespace *sub;
  408 + struct aa_profile *child;
  409 + int i;
  410 +
  411 + if (!ns)
  412 + return;
  413 +
  414 + list_for_each_entry(child, &ns->base.profiles, base.list)
  415 + __aa_fs_profile_rmdir(child);
  416 +
  417 + list_for_each_entry(sub, &ns->sub_ns, base.list) {
  418 + mutex_lock(&sub->lock);
  419 + __aa_fs_namespace_rmdir(sub);
  420 + mutex_unlock(&sub->lock);
  421 + }
  422 +
  423 + for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
  424 + securityfs_remove(ns->dents[i]);
  425 + ns->dents[i] = NULL;
  426 + }
  427 +}
  428 +
  429 +int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
  430 + const char *name)
  431 +{
  432 + struct aa_namespace *sub;
  433 + struct aa_profile *child;
  434 + struct dentry *dent, *dir;
  435 + int error;
  436 +
  437 + if (!name)
  438 + name = ns->base.name;
  439 +
  440 + dent = securityfs_create_dir(name, parent);
  441 + if (IS_ERR(dent))
  442 + goto fail;
  443 + ns_dir(ns) = dir = dent;
  444 +
  445 + dent = securityfs_create_dir("profiles", dir);
  446 + if (IS_ERR(dent))
  447 + goto fail;
  448 + ns_subprofs_dir(ns) = dent;
  449 +
  450 + dent = securityfs_create_dir("namespaces", dir);
  451 + if (IS_ERR(dent))
  452 + goto fail;
  453 + ns_subns_dir(ns) = dent;
  454 +
  455 + list_for_each_entry(child, &ns->base.profiles, base.list) {
  456 + error = __aa_fs_profile_mkdir(child, ns_subprofs_dir(ns));
  457 + if (error)
  458 + goto fail2;
  459 + }
  460 +
  461 + list_for_each_entry(sub, &ns->sub_ns, base.list) {
  462 + mutex_lock(&sub->lock);
  463 + error = __aa_fs_namespace_mkdir(sub, ns_subns_dir(ns), NULL);
  464 + mutex_unlock(&sub->lock);
  465 + if (error)
  466 + goto fail2;
  467 + }
  468 +
  469 + return 0;
  470 +
  471 +fail:
  472 + error = PTR_ERR(dent);
  473 +
  474 +fail2:
  475 + __aa_fs_namespace_rmdir(ns);
  476 +
  477 + return error;
  478 +}
  479 +
  480 +
  481 +/** Base file system setup **/
187 482 static struct aa_fs_entry aa_fs_entry_file[] = {
188 483 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
189 484 "link lock"),
... ... @@ -246,6 +541,7 @@
246 541 return error;
247 542 }
248 543  
  544 +static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);
249 545 /**
250 546 * aafs_create_dir - recursively create a directory entry in the securityfs
251 547 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
252 548  
253 549  
254 550  
... ... @@ -256,17 +552,16 @@
256 552 static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
257 553 struct dentry *parent)
258 554 {
259   - int error;
260 555 struct aa_fs_entry *fs_file;
  556 + struct dentry *dir;
  557 + int error;
261 558  
262   - fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent);
263   - if (IS_ERR(fs_dir->dentry)) {
264   - error = PTR_ERR(fs_dir->dentry);
265   - fs_dir->dentry = NULL;
266   - goto failed;
267   - }
  559 + dir = securityfs_create_dir(fs_dir->name, parent);
  560 + if (IS_ERR(dir))
  561 + return PTR_ERR(dir);
  562 + fs_dir->dentry = dir;
268 563  
269   - for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
  564 + for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
270 565 if (fs_file->v_type == AA_FS_TYPE_DIR)
271 566 error = aafs_create_dir(fs_file, fs_dir->dentry);
272 567 else
... ... @@ -278,6 +573,8 @@
278 573 return 0;
279 574  
280 575 failed:
  576 + aafs_remove_dir(fs_dir);
  577 +
281 578 return error;
282 579 }
283 580  
... ... @@ -302,7 +599,7 @@
302 599 {
303 600 struct aa_fs_entry *fs_file;
304 601  
305   - for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
  602 + for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
306 603 if (fs_file->v_type == AA_FS_TYPE_DIR)
307 604 aafs_remove_dir(fs_file);
308 605 else
... ... @@ -343,6 +640,11 @@
343 640  
344 641 /* Populate fs tree. */
345 642 error = aafs_create_dir(&aa_fs_entry, NULL);
  643 + if (error)
  644 + goto error;
  645 +
  646 + error = __aa_fs_namespace_mkdir(root_ns, aa_fs_entry.dentry,
  647 + "policy");
346 648 if (error)
347 649 goto error;
348 650  
security/apparmor/include/apparmorfs.h
... ... @@ -61,5 +61,43 @@
61 61  
62 62 extern void __init aa_destroy_aafs(void);
63 63  
  64 +struct aa_profile;
  65 +struct aa_namespace;
  66 +
  67 +enum aafs_ns_type {
  68 + AAFS_NS_DIR,
  69 + AAFS_NS_PROFS,
  70 + AAFS_NS_NS,
  71 + AAFS_NS_COUNT,
  72 + AAFS_NS_MAX_COUNT,
  73 + AAFS_NS_SIZE,
  74 + AAFS_NS_MAX_SIZE,
  75 + AAFS_NS_OWNER,
  76 + AAFS_NS_SIZEOF,
  77 +};
  78 +
  79 +enum aafs_prof_type {
  80 + AAFS_PROF_DIR,
  81 + AAFS_PROF_PROFS,
  82 + AAFS_PROF_NAME,
  83 + AAFS_PROF_MODE,
  84 + AAFS_PROF_SIZEOF,
  85 +};
  86 +
  87 +#define ns_dir(X) ((X)->dents[AAFS_NS_DIR])
  88 +#define ns_subns_dir(X) ((X)->dents[AAFS_NS_NS])
  89 +#define ns_subprofs_dir(X) ((X)->dents[AAFS_NS_PROFS])
  90 +
  91 +#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
  92 +#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
  93 +
  94 +void __aa_fs_profile_rmdir(struct aa_profile *profile);
  95 +void __aa_fs_profile_migrate_dents(struct aa_profile *old,
  96 + struct aa_profile *new);
  97 +int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
  98 +void __aa_fs_namespace_rmdir(struct aa_namespace *ns);
  99 +int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
  100 + const char *name);
  101 +
64 102 #endif /* __AA_APPARMORFS_H */
security/apparmor/include/audit.h
... ... @@ -27,7 +27,6 @@
27 27  
28 28 extern const char *const audit_mode_names[];
29 29 #define AUDIT_MAX_INDEX 5
30   -
31 30 enum audit_mode {
32 31 AUDIT_NORMAL, /* follow normal auditing of accesses */
33 32 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
security/apparmor/include/policy.h
... ... @@ -29,8 +29,8 @@
29 29 #include "file.h"
30 30 #include "resource.h"
31 31  
32   -extern const char *const profile_mode_names[];
33   -#define APPARMOR_NAMES_MAX_INDEX 3
  32 +extern const char *const aa_profile_mode_names[];
  33 +#define APPARMOR_MODE_NAMES_MAX_INDEX 4
34 34  
35 35 #define PROFILE_MODE(_profile, _mode) \
36 36 ((aa_g_profile_mode == (_mode)) || \
... ... @@ -110,6 +110,8 @@
110 110 * @unconfined: special unconfined profile for the namespace
111 111 * @sub_ns: list of namespaces under the current namespace.
112 112 * @uniq_null: uniq value used for null learning profiles
  113 + * @uniq_id: a unique id count for the profiles in the namespace
  114 + * @dents: dentries for the namespaces file entries in apparmorfs
113 115 *
114 116 * An aa_namespace defines the set profiles that are searched to determine
115 117 * which profile to attach to a task. Profiles can not be shared between
... ... @@ -133,6 +135,9 @@
133 135 struct aa_profile *unconfined;
134 136 struct list_head sub_ns;
135 137 atomic_t uniq_null;
  138 + long uniq_id;
  139 +
  140 + struct dentry *dents[AAFS_NS_SIZEOF];
136 141 };
137 142  
138 143 /* struct aa_policydb - match engine for a policy
... ... @@ -172,6 +177,9 @@
172 177 * @caps: capabilities for the profile
173 178 * @rlimits: rlimits for the profile
174 179 *
  180 + * @dents: dentries for the profiles file entries in apparmorfs
  181 + * @dirname: name of the profile dir in apparmorfs
  182 + *
175 183 * The AppArmor profile contains the basic confinement data. Each profile
176 184 * has a name, and exists in a namespace. The @name and @exec_match are
177 185 * used to determine profile attachment against unconfined tasks. All other
... ... @@ -208,6 +216,9 @@
208 216 struct aa_file_rules file;
209 217 struct aa_caps caps;
210 218 struct aa_rlimit rlimits;
  219 +
  220 + char *dirname;
  221 + struct dentry *dents[AAFS_PROF_SIZEOF];
211 222 };
212 223  
213 224 extern struct aa_namespace *root_ns;
... ... @@ -242,6 +253,12 @@
242 253  
243 254 #define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
244 255  
  256 +
  257 +static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)
  258 +{
  259 + return rcu_dereference_protected(p->parent,
  260 + mutex_is_locked(&p->ns->lock));
  261 +}
245 262  
246 263 /**
247 264 * aa_get_profile - increment refcount on profile @p
security/apparmor/lsm.c
... ... @@ -843,7 +843,7 @@
843 843 if (!apparmor_enabled)
844 844 return -EINVAL;
845 845  
846   - return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
  846 + return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
847 847 }
848 848  
849 849 static int param_set_mode(const char *val, struct kernel_param *kp)
... ... @@ -858,8 +858,8 @@
858 858 if (!val)
859 859 return -EINVAL;
860 860  
861   - for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
862   - if (strcmp(val, profile_mode_names[i]) == 0) {
  861 + for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) {
  862 + if (strcmp(val, aa_profile_mode_names[i]) == 0) {
863 863 aa_g_profile_mode = i;
864 864 return 0;
865 865 }
security/apparmor/policy.c
... ... @@ -92,7 +92,7 @@
92 92 /* root profile namespace */
93 93 struct aa_namespace *root_ns;
94 94  
95   -const char *const profile_mode_names[] = {
  95 +const char *const aa_profile_mode_names[] = {
96 96 "enforce",
97 97 "complain",
98 98 "kill",
... ... @@ -394,7 +394,13 @@
394 394 ns = alloc_namespace(root->base.hname, name);
395 395 if (!ns)
396 396 goto out;
397   - /* add parent ref */
  397 + if (__aa_fs_namespace_mkdir(ns, ns_subns_dir(root), name)) {
  398 + AA_ERROR("Failed to create interface for ns %s\n",
  399 + ns->base.name);
  400 + free_namespace(ns);
  401 + ns = NULL;
  402 + goto out;
  403 + }
398 404 ns->parent = aa_get_namespace(root);
399 405 list_add_rcu(&ns->base.list, &root->sub_ns);
400 406 /* add list ref */
... ... @@ -456,6 +462,7 @@
456 462 __profile_list_release(&profile->base.profiles);
457 463 /* released by free_profile */
458 464 __aa_update_replacedby(profile, profile->ns->unconfined);
  465 + __aa_fs_profile_rmdir(profile);
459 466 __list_remove_profile(profile);
460 467 }
461 468  
... ... @@ -492,6 +499,7 @@
492 499  
493 500 if (ns->parent)
494 501 __aa_update_replacedby(ns->unconfined, ns->parent->unconfined);
  502 + __aa_fs_namespace_rmdir(ns);
495 503 mutex_unlock(&ns->lock);
496 504 }
497 505  
... ... @@ -596,6 +604,7 @@
596 604 aa_free_cap_rules(&profile->caps);
597 605 aa_free_rlimit_rules(&profile->rlimits);
598 606  
  607 + kzfree(profile->dirname);
599 608 aa_put_dfa(profile->xmatch);
600 609 aa_put_dfa(profile->policy.dfa);
601 610 aa_put_replacedby(profile->replacedby);
... ... @@ -986,8 +995,7 @@
986 995 /* inherit @child and its children */
987 996 /* TODO: update hname of inherited children */
988 997 /* list refcount transferred to @new */
989   - p = rcu_dereference_protected(child->parent,
990   - mutex_is_locked(&child->ns->lock));
  998 + p = aa_deref_parent(child);
991 999 rcu_assign_pointer(child->parent, aa_get_profile(new));
992 1000 list_add_rcu(&child->base.list, &new->base.profiles);
993 1001 aa_put_profile(p);
994 1002  
... ... @@ -995,14 +1003,18 @@
995 1003 }
996 1004  
997 1005 if (!rcu_access_pointer(new->parent)) {
998   - struct aa_profile *parent = rcu_dereference(old->parent);
  1006 + struct aa_profile *parent = aa_deref_parent(old);
999 1007 rcu_assign_pointer(new->parent, aa_get_profile(parent));
1000 1008 }
1001 1009 __aa_update_replacedby(old, new);
1002 1010 if (share_replacedby) {
1003 1011 aa_put_replacedby(new->replacedby);
1004 1012 new->replacedby = aa_get_replacedby(old->replacedby);
1005   - }
  1013 + } else if (!rcu_access_pointer(new->replacedby->profile))
  1014 + /* aafs interface uses replacedby */
  1015 + rcu_assign_pointer(new->replacedby->profile,
  1016 + aa_get_profile(new));
  1017 + __aa_fs_profile_migrate_dents(old, new);
1006 1018  
1007 1019 if (list_empty(&new->base.list)) {
1008 1020 /* new is not on a list already */
... ... @@ -1118,7 +1130,33 @@
1118 1130 }
1119 1131 }
1120 1132  
1121   - /* do actual replacement */
  1133 + /* create new fs entries for introspection if needed */
  1134 + list_for_each_entry(ent, &lh, list) {
  1135 + if (ent->old) {
  1136 + /* inherit old interface files */
  1137 +
  1138 + /* if (ent->rename)
  1139 + TODO: support rename */
  1140 + /* } else if (ent->rename) {
  1141 + TODO: support rename */
  1142 + } else {
  1143 + struct dentry *parent;
  1144 + if (rcu_access_pointer(ent->new->parent)) {
  1145 + struct aa_profile *p;
  1146 + p = aa_deref_parent(ent->new);
  1147 + parent = prof_child_dir(p);
  1148 + } else
  1149 + parent = ns_subprofs_dir(ent->new->ns);
  1150 + error = __aa_fs_profile_mkdir(ent->new, parent);
  1151 + }
  1152 +
  1153 + if (error) {
  1154 + info = "failed to create ";
  1155 + goto fail_lock;
  1156 + }
  1157 + }
  1158 +
  1159 + /* Done with checks that may fail - do actual replacement */
1122 1160 list_for_each_entry_safe(ent, tmp, &lh, list) {
1123 1161 list_del_init(&ent->list);
1124 1162 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
1125 1163  
1126 1164  
1127 1165  
... ... @@ -1127,14 +1165,21 @@
1127 1165  
1128 1166 if (ent->old) {
1129 1167 __replace_profile(ent->old, ent->new, 1);
1130   - if (ent->rename)
  1168 + if (ent->rename) {
  1169 + /* aafs interface uses replacedby */
  1170 + struct aa_replacedby *r = ent->new->replacedby;
  1171 + rcu_assign_pointer(r->profile,
  1172 + aa_get_profile(ent->new));
1131 1173 __replace_profile(ent->rename, ent->new, 0);
  1174 + }
1132 1175 } else if (ent->rename) {
  1176 + /* aafs interface uses replacedby */
  1177 + rcu_assign_pointer(ent->new->replacedby->profile,
  1178 + aa_get_profile(ent->new));
1133 1179 __replace_profile(ent->rename, ent->new, 0);
1134 1180 } else if (ent->new->parent) {
1135 1181 struct aa_profile *parent, *newest;
1136   - parent = rcu_dereference_protected(ent->new->parent,
1137   - mutex_is_locked(&ns->lock));
  1182 + parent = aa_deref_parent(ent->new);
1138 1183 newest = aa_get_newest_profile(parent);
1139 1184  
1140 1185 /* parent replaced in this atomic set? */
1141 1186  
1142 1187  
... ... @@ -1144,10 +1189,16 @@
1144 1189 rcu_assign_pointer(ent->new->parent, newest);
1145 1190 } else
1146 1191 aa_put_profile(newest);
  1192 + /* aafs interface uses replacedby */
  1193 + rcu_assign_pointer(ent->new->replacedby->profile,
  1194 + aa_get_profile(ent->new));
1147 1195 __list_add_profile(&parent->base.profiles, ent->new);
1148   - } else
  1196 + } else {
  1197 + /* aafs interface uses replacedby */
  1198 + rcu_assign_pointer(ent->new->replacedby->profile,
  1199 + aa_get_profile(ent->new));
1149 1200 __list_add_profile(&ns->base.profiles, ent->new);
1150   -
  1201 + }
1151 1202 aa_load_ent_free(ent);
1152 1203 }
1153 1204 mutex_unlock(&ns->lock);
security/apparmor/procattr.c
... ... @@ -37,7 +37,7 @@
37 37 {
38 38 char *str;
39 39 int len = 0, mode_len = 0, ns_len = 0, name_len;
40   - const char *mode_str = profile_mode_names[profile->mode];
  40 + const char *mode_str = aa_profile_mode_names[profile->mode];
41 41 const char *ns_name = NULL;
42 42 struct aa_namespace *ns = profile->ns;
43 43 struct aa_namespace *current_ns = __aa_current_profile()->ns;