diff options
Diffstat (limited to 'security/apparmor/path.c')
| -rw-r--r-- | security/apparmor/path.c | 38 |
1 files changed, 11 insertions, 27 deletions
diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 19358dc14605..82396050f186 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c | |||
| @@ -59,8 +59,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
| 59 | { | 59 | { |
| 60 | struct path root, tmp; | 60 | struct path root, tmp; |
| 61 | char *res; | 61 | char *res; |
| 62 | int deleted, connected; | 62 | int connected, error = 0; |
| 63 | int error = 0; | ||
| 64 | 63 | ||
| 65 | /* Get the root we want to resolve too, released below */ | 64 | /* Get the root we want to resolve too, released below */ |
| 66 | if (flags & PATH_CHROOT_REL) { | 65 | if (flags & PATH_CHROOT_REL) { |
| @@ -74,19 +73,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | spin_lock(&dcache_lock); | 75 | spin_lock(&dcache_lock); |
| 77 | /* There is a race window between path lookup here and the | 76 | tmp = root; |
| 78 | * need to strip the " (deleted) string that __d_path applies | 77 | res = __d_path(path, &tmp, buf, buflen); |
| 79 | * Detect the race and relookup the path | ||
| 80 | * | ||
| 81 | * The stripping of (deleted) is a hack that could be removed | ||
| 82 | * with an updated __d_path | ||
| 83 | */ | ||
| 84 | do { | ||
| 85 | tmp = root; | ||
| 86 | deleted = d_unlinked(path->dentry); | ||
| 87 | res = __d_path(path, &tmp, buf, buflen); | ||
| 88 | |||
| 89 | } while (deleted != d_unlinked(path->dentry)); | ||
| 90 | spin_unlock(&dcache_lock); | 78 | spin_unlock(&dcache_lock); |
| 91 | 79 | ||
| 92 | *name = res; | 80 | *name = res; |
| @@ -98,21 +86,17 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
| 98 | *name = buf; | 86 | *name = buf; |
| 99 | goto out; | 87 | goto out; |
| 100 | } | 88 | } |
| 101 | if (deleted) { | ||
| 102 | /* On some filesystems, newly allocated dentries appear to the | ||
| 103 | * security_path hooks as a deleted dentry except without an | ||
| 104 | * inode allocated. | ||
| 105 | * | ||
| 106 | * Remove the appended deleted text and return as string for | ||
| 107 | * normal mediation, or auditing. The (deleted) string is | ||
| 108 | * guaranteed to be added in this case, so just strip it. | ||
| 109 | */ | ||
| 110 | buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */ | ||
| 111 | 89 | ||
| 112 | if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { | 90 | /* Handle two cases: |
| 91 | * 1. A deleted dentry && profile is not allowing mediation of deleted | ||
| 92 | * 2. On some filesystems, newly allocated dentries appear to the | ||
| 93 | * security_path hooks as a deleted dentry except without an inode | ||
| 94 | * allocated. | ||
| 95 | */ | ||
| 96 | if (d_unlinked(path->dentry) && path->dentry->d_inode && | ||
| 97 | !(flags & PATH_MEDIATE_DELETED)) { | ||
| 113 | error = -ENOENT; | 98 | error = -ENOENT; |
| 114 | goto out; | 99 | goto out; |
| 115 | } | ||
| 116 | } | 100 | } |
| 117 | 101 | ||
| 118 | /* Determine if the path is connected to the expected root */ | 102 | /* Determine if the path is connected to the expected root */ |
