diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/apparmor/include/resource.h | 4 | ||||
| -rw-r--r-- | security/apparmor/lib.c | 2 | ||||
| -rw-r--r-- | security/apparmor/lsm.c | 2 | ||||
| -rw-r--r-- | security/apparmor/path.c | 38 | ||||
| -rw-r--r-- | security/apparmor/policy.c | 6 | ||||
| -rw-r--r-- | security/apparmor/resource.c | 20 | ||||
| -rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
| -rw-r--r-- | security/integrity/ima/ima_iint.c | 4 | ||||
| -rw-r--r-- | security/integrity/ima/ima_main.c | 8 | ||||
| -rw-r--r-- | security/keys/keyctl.c | 6 | ||||
| -rw-r--r-- | security/tomoyo/common.c | 6 | ||||
| -rw-r--r-- | security/tomoyo/common.h | 3 |
12 files changed, 50 insertions, 50 deletions
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h index 3c88be946494..02baec732bb5 100644 --- a/security/apparmor/include/resource.h +++ b/security/apparmor/include/resource.h | |||
| @@ -33,8 +33,8 @@ struct aa_rlimit { | |||
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | int aa_map_resource(int resource); | 35 | int aa_map_resource(int resource); |
| 36 | int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, | 36 | int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, |
| 37 | struct rlimit *new_rlim); | 37 | unsigned int resource, struct rlimit *new_rlim); |
| 38 | 38 | ||
| 39 | void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); | 39 | void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); |
| 40 | 40 | ||
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 6e85cdb4303f..506d2baf6147 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
| @@ -40,6 +40,7 @@ char *aa_split_fqname(char *fqname, char **ns_name) | |||
| 40 | *ns_name = NULL; | 40 | *ns_name = NULL; |
| 41 | if (name[0] == ':') { | 41 | if (name[0] == ':') { |
| 42 | char *split = strchr(&name[1], ':'); | 42 | char *split = strchr(&name[1], ':'); |
| 43 | *ns_name = skip_spaces(&name[1]); | ||
| 43 | if (split) { | 44 | if (split) { |
| 44 | /* overwrite ':' with \0 */ | 45 | /* overwrite ':' with \0 */ |
| 45 | *split = 0; | 46 | *split = 0; |
| @@ -47,7 +48,6 @@ char *aa_split_fqname(char *fqname, char **ns_name) | |||
| 47 | } else | 48 | } else |
| 48 | /* a ns name without a following profile is allowed */ | 49 | /* a ns name without a following profile is allowed */ |
| 49 | name = NULL; | 50 | name = NULL; |
| 50 | *ns_name = &name[1]; | ||
| 51 | } | 51 | } |
| 52 | if (name && *name == 0) | 52 | if (name && *name == 0) |
| 53 | name = NULL; | 53 | name = NULL; |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index f73e2c204218..cf1de4462ccd 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -614,7 +614,7 @@ static int apparmor_task_setrlimit(struct task_struct *task, | |||
| 614 | int error = 0; | 614 | int error = 0; |
| 615 | 615 | ||
| 616 | if (!unconfined(profile)) | 616 | if (!unconfined(profile)) |
| 617 | error = aa_task_setrlimit(profile, resource, new_rlim); | 617 | error = aa_task_setrlimit(profile, task, resource, new_rlim); |
| 618 | 618 | ||
| 619 | return error; | 619 | return error; |
| 620 | } | 620 | } |
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 */ |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 3cdc1ad0787e..52cc865f1464 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
| @@ -1151,12 +1151,14 @@ ssize_t aa_remove_profiles(char *fqname, size_t size) | |||
| 1151 | /* released below */ | 1151 | /* released below */ |
| 1152 | ns = aa_get_namespace(root); | 1152 | ns = aa_get_namespace(root); |
| 1153 | 1153 | ||
| 1154 | write_lock(&ns->lock); | ||
| 1155 | if (!name) { | 1154 | if (!name) { |
| 1156 | /* remove namespace - can only happen if fqname[0] == ':' */ | 1155 | /* remove namespace - can only happen if fqname[0] == ':' */ |
| 1156 | write_lock(&ns->parent->lock); | ||
| 1157 | __remove_namespace(ns); | 1157 | __remove_namespace(ns); |
| 1158 | write_unlock(&ns->parent->lock); | ||
| 1158 | } else { | 1159 | } else { |
| 1159 | /* remove profile */ | 1160 | /* remove profile */ |
| 1161 | write_lock(&ns->lock); | ||
| 1160 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); | 1162 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); |
| 1161 | if (!profile) { | 1163 | if (!profile) { |
| 1162 | error = -ENOENT; | 1164 | error = -ENOENT; |
| @@ -1165,8 +1167,8 @@ ssize_t aa_remove_profiles(char *fqname, size_t size) | |||
| 1165 | } | 1167 | } |
| 1166 | name = profile->base.hname; | 1168 | name = profile->base.hname; |
| 1167 | __remove_profile(profile); | 1169 | __remove_profile(profile); |
| 1170 | write_unlock(&ns->lock); | ||
| 1168 | } | 1171 | } |
| 1169 | write_unlock(&ns->lock); | ||
| 1170 | 1172 | ||
| 1171 | /* don't fail removal if audit fails */ | 1173 | /* don't fail removal if audit fails */ |
| 1172 | (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); | 1174 | (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); |
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 4a368f1fd36d..a4136c10b1c6 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c | |||
| @@ -72,6 +72,7 @@ int aa_map_resource(int resource) | |||
| 72 | /** | 72 | /** |
| 73 | * aa_task_setrlimit - test permission to set an rlimit | 73 | * aa_task_setrlimit - test permission to set an rlimit |
| 74 | * @profile - profile confining the task (NOT NULL) | 74 | * @profile - profile confining the task (NOT NULL) |
| 75 | * @task - task the resource is being set on | ||
| 75 | * @resource - the resource being set | 76 | * @resource - the resource being set |
| 76 | * @new_rlim - the new resource limit (NOT NULL) | 77 | * @new_rlim - the new resource limit (NOT NULL) |
| 77 | * | 78 | * |
| @@ -79,18 +80,21 @@ int aa_map_resource(int resource) | |||
| 79 | * | 80 | * |
| 80 | * Returns: 0 or error code if setting resource failed | 81 | * Returns: 0 or error code if setting resource failed |
| 81 | */ | 82 | */ |
| 82 | int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, | 83 | int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, |
| 83 | struct rlimit *new_rlim) | 84 | unsigned int resource, struct rlimit *new_rlim) |
| 84 | { | 85 | { |
| 85 | int error = 0; | 86 | int error = 0; |
| 86 | 87 | ||
| 87 | if (profile->rlimits.mask & (1 << resource) && | 88 | /* TODO: extend resource control to handle other (non current) |
| 88 | new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) | 89 | * processes. AppArmor rules currently have the implicit assumption |
| 89 | 90 | * that the task is setting the resource of the current process | |
| 90 | error = audit_resource(profile, resource, new_rlim->rlim_max, | 91 | */ |
| 91 | -EACCES); | 92 | if ((task != current->group_leader) || |
| 93 | (profile->rlimits.mask & (1 << resource) && | ||
| 94 | new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) | ||
| 95 | error = -EACCES; | ||
| 92 | 96 | ||
| 93 | return error; | 97 | return audit_resource(profile, resource, new_rlim->rlim_max, error); |
| 94 | } | 98 | } |
| 95 | 99 | ||
| 96 | /** | 100 | /** |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 16d100d3fc38..3fbcd1dda0ef 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
| @@ -35,6 +35,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | |||
| 35 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) | 35 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) |
| 36 | 36 | ||
| 37 | /* set during initialization */ | 37 | /* set during initialization */ |
| 38 | extern int iint_initialized; | ||
| 38 | extern int ima_initialized; | 39 | extern int ima_initialized; |
| 39 | extern int ima_used_chip; | 40 | extern int ima_used_chip; |
| 40 | extern char *ima_hash; | 41 | extern char *ima_hash; |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 7625b85c2274..afba4aef812f 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
| @@ -22,9 +22,10 @@ | |||
| 22 | 22 | ||
| 23 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); | 23 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); |
| 24 | DEFINE_SPINLOCK(ima_iint_lock); | 24 | DEFINE_SPINLOCK(ima_iint_lock); |
| 25 | |||
| 26 | static struct kmem_cache *iint_cache __read_mostly; | 25 | static struct kmem_cache *iint_cache __read_mostly; |
| 27 | 26 | ||
| 27 | int iint_initialized = 0; | ||
| 28 | |||
| 28 | /* ima_iint_find_get - return the iint associated with an inode | 29 | /* ima_iint_find_get - return the iint associated with an inode |
| 29 | * | 30 | * |
| 30 | * ima_iint_find_get gets a reference to the iint. Caller must | 31 | * ima_iint_find_get gets a reference to the iint. Caller must |
| @@ -141,6 +142,7 @@ static int __init ima_iintcache_init(void) | |||
| 141 | iint_cache = | 142 | iint_cache = |
| 142 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, | 143 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, |
| 143 | SLAB_PANIC, init_once); | 144 | SLAB_PANIC, init_once); |
| 145 | iint_initialized = 1; | ||
| 144 | return 0; | 146 | return 0; |
| 145 | } | 147 | } |
| 146 | security_initcall(ima_iintcache_init); | 148 | security_initcall(ima_iintcache_init); |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f93641382e9f..e662b89d4079 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -148,12 +148,14 @@ void ima_counts_get(struct file *file) | |||
| 148 | struct ima_iint_cache *iint; | 148 | struct ima_iint_cache *iint; |
| 149 | int rc; | 149 | int rc; |
| 150 | 150 | ||
| 151 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 151 | if (!iint_initialized || !S_ISREG(inode->i_mode)) |
| 152 | return; | 152 | return; |
| 153 | iint = ima_iint_find_get(inode); | 153 | iint = ima_iint_find_get(inode); |
| 154 | if (!iint) | 154 | if (!iint) |
| 155 | return; | 155 | return; |
| 156 | mutex_lock(&iint->mutex); | 156 | mutex_lock(&iint->mutex); |
| 157 | if (!ima_initialized) | ||
| 158 | goto out; | ||
| 157 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); | 159 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); |
| 158 | if (rc < 0) | 160 | if (rc < 0) |
| 159 | goto out; | 161 | goto out; |
| @@ -213,7 +215,7 @@ void ima_file_free(struct file *file) | |||
| 213 | struct inode *inode = file->f_dentry->d_inode; | 215 | struct inode *inode = file->f_dentry->d_inode; |
| 214 | struct ima_iint_cache *iint; | 216 | struct ima_iint_cache *iint; |
| 215 | 217 | ||
| 216 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 218 | if (!iint_initialized || !S_ISREG(inode->i_mode)) |
| 217 | return; | 219 | return; |
| 218 | iint = ima_iint_find_get(inode); | 220 | iint = ima_iint_find_get(inode); |
| 219 | if (!iint) | 221 | if (!iint) |
| @@ -230,7 +232,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, | |||
| 230 | { | 232 | { |
| 231 | struct inode *inode = file->f_dentry->d_inode; | 233 | struct inode *inode = file->f_dentry->d_inode; |
| 232 | struct ima_iint_cache *iint; | 234 | struct ima_iint_cache *iint; |
| 233 | int rc; | 235 | int rc = 0; |
| 234 | 236 | ||
| 235 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 237 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
| 236 | return 0; | 238 | return 0; |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b2b0998d6abd..60924f6a52db 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -1272,6 +1272,7 @@ long keyctl_session_to_parent(void) | |||
| 1272 | keyring_r = NULL; | 1272 | keyring_r = NULL; |
| 1273 | 1273 | ||
| 1274 | me = current; | 1274 | me = current; |
| 1275 | rcu_read_lock(); | ||
| 1275 | write_lock_irq(&tasklist_lock); | 1276 | write_lock_irq(&tasklist_lock); |
| 1276 | 1277 | ||
| 1277 | parent = me->real_parent; | 1278 | parent = me->real_parent; |
| @@ -1304,7 +1305,8 @@ long keyctl_session_to_parent(void) | |||
| 1304 | goto not_permitted; | 1305 | goto not_permitted; |
| 1305 | 1306 | ||
| 1306 | /* the keyrings must have the same UID */ | 1307 | /* the keyrings must have the same UID */ |
| 1307 | if (pcred->tgcred->session_keyring->uid != mycred->euid || | 1308 | if ((pcred->tgcred->session_keyring && |
| 1309 | pcred->tgcred->session_keyring->uid != mycred->euid) || | ||
| 1308 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1310 | mycred->tgcred->session_keyring->uid != mycred->euid) |
| 1309 | goto not_permitted; | 1311 | goto not_permitted; |
| 1310 | 1312 | ||
| @@ -1319,6 +1321,7 @@ long keyctl_session_to_parent(void) | |||
| 1319 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | 1321 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); |
| 1320 | 1322 | ||
| 1321 | write_unlock_irq(&tasklist_lock); | 1323 | write_unlock_irq(&tasklist_lock); |
| 1324 | rcu_read_unlock(); | ||
| 1322 | if (oldcred) | 1325 | if (oldcred) |
| 1323 | put_cred(oldcred); | 1326 | put_cred(oldcred); |
| 1324 | return 0; | 1327 | return 0; |
| @@ -1327,6 +1330,7 @@ already_same: | |||
| 1327 | ret = 0; | 1330 | ret = 0; |
| 1328 | not_permitted: | 1331 | not_permitted: |
| 1329 | write_unlock_irq(&tasklist_lock); | 1332 | write_unlock_irq(&tasklist_lock); |
| 1333 | rcu_read_unlock(); | ||
| 1330 | put_cred(cred); | 1334 | put_cred(cred); |
| 1331 | return ret; | 1335 | return ret; |
| 1332 | 1336 | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef43995119a4..c668b447c725 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
| @@ -1416,15 +1416,19 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
| 1416 | const pid_t gpid = task_pid_nr(current); | 1416 | const pid_t gpid = task_pid_nr(current); |
| 1417 | static const int tomoyo_buffer_len = 4096; | 1417 | static const int tomoyo_buffer_len = 4096; |
| 1418 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | 1418 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); |
| 1419 | pid_t ppid; | ||
| 1419 | if (!buffer) | 1420 | if (!buffer) |
| 1420 | return NULL; | 1421 | return NULL; |
| 1421 | do_gettimeofday(&tv); | 1422 | do_gettimeofday(&tv); |
| 1423 | rcu_read_lock(); | ||
| 1424 | ppid = task_tgid_vnr(current->real_parent); | ||
| 1425 | rcu_read_unlock(); | ||
| 1422 | snprintf(buffer, tomoyo_buffer_len - 1, | 1426 | snprintf(buffer, tomoyo_buffer_len - 1, |
| 1423 | "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" | 1427 | "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" |
| 1424 | " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" | 1428 | " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" |
| 1425 | " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", | 1429 | " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", |
| 1426 | tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, | 1430 | tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, |
| 1427 | (pid_t) sys_getpid(), (pid_t) sys_getppid(), | 1431 | task_tgid_vnr(current), ppid, |
| 1428 | current_uid(), current_gid(), current_euid(), | 1432 | current_uid(), current_gid(), current_euid(), |
| 1429 | current_egid(), current_suid(), current_sgid(), | 1433 | current_egid(), current_suid(), current_sgid(), |
| 1430 | current_fsuid(), current_fsgid()); | 1434 | current_fsuid(), current_fsgid()); |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 04454cb7b24a..7c66bd898782 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
| @@ -689,9 +689,6 @@ struct tomoyo_profile { | |||
| 689 | 689 | ||
| 690 | /********** Function prototypes. **********/ | 690 | /********** Function prototypes. **********/ |
| 691 | 691 | ||
| 692 | extern asmlinkage long sys_getpid(void); | ||
| 693 | extern asmlinkage long sys_getppid(void); | ||
| 694 | |||
| 695 | /* Check whether the given string starts with the given keyword. */ | 692 | /* Check whether the given string starts with the given keyword. */ |
| 696 | bool tomoyo_str_starts(char **src, const char *find); | 693 | bool tomoyo_str_starts(char **src, const char *find); |
| 697 | /* Get tomoyo_realpath() of current process. */ | 694 | /* Get tomoyo_realpath() of current process. */ |
