diff options
Diffstat (limited to 'security/tomoyo/realpath.c')
-rw-r--r-- | security/tomoyo/realpath.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 6ff8c21e4fff..85e6e31dd1e5 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -94,11 +94,13 @@ static char *tomoyo_get_absolute_path(const struct path *path, char * const buff const int buflen) { char *pos = ERR_PTR(-ENOMEM); + if (buflen >= 256) { /* go to whatever namespace root we are under */ pos = d_absolute_path(path, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = d_backing_inode(path->dentry); + if (inode && S_ISDIR(inode->i_mode)) { buffer[buflen - 2] = '/'; buffer[buflen - 1] = '\0'; @@ -123,10 +125,12 @@ static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer, const int buflen) { char *pos = ERR_PTR(-ENOMEM); + if (buflen >= 256) { pos = dentry_path_raw(dentry, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = d_backing_inode(dentry); + if (inode && S_ISDIR(inode->i_mode)) { buffer[buflen - 2] = '/'; buffer[buflen - 1] = '\0'; @@ -150,12 +154,14 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, { struct super_block *sb = dentry->d_sb; char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen); + if (IS_ERR(pos)) return pos; /* Convert from $PID to self if $PID is current thread. */ if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { char *ep; const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); + if (*ep == '/' && pid && pid == task_tgid_nr_ns(current, sb->s_fs_info)) { pos = ep - 5; @@ -170,6 +176,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, goto prepend_filesystem_name; { struct inode *inode = d_backing_inode(sb->s_root); + /* * Use filesystem name if filesystem does not support rename() * operation. @@ -182,6 +189,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, char name[64]; int name_len; const dev_t dev = sb->s_dev; + name[sizeof(name) - 1] = '\0'; snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev), MINOR(dev)); @@ -197,6 +205,7 @@ prepend_filesystem_name: { const char *name = sb->s_type->name; const int name_len = strlen(name); + pos -= name_len + 1; if (pos < buffer) goto out; @@ -223,10 +232,10 @@ static char *tomoyo_get_socket_name(const struct path *path, char * const buffer struct inode *inode = d_backing_inode(path->dentry); struct socket *sock = inode ? SOCKET_I(inode) : NULL; struct sock *sk = sock ? sock->sk : NULL; + if (sk) { - snprintf(buffer, buflen, "socket:[family=%u:type=%u:" - "protocol=%u]", sk->sk_family, sk->sk_type, - sk->sk_protocol); + snprintf(buffer, buflen, "socket:[family=%u:type=%u:protocol=%u]", + sk->sk_family, sk->sk_type, sk->sk_protocol); } else { snprintf(buffer, buflen, "socket:[unknown]"); } @@ -255,12 +264,14 @@ char *tomoyo_realpath_from_path(const struct path *path) unsigned int buf_len = PAGE_SIZE / 2; struct dentry *dentry = path->dentry; struct super_block *sb; + if (!dentry) return NULL; sb = dentry->d_sb; while (1) { char *pos; struct inode *inode; + buf_len <<= 1; kfree(buf); buf = kmalloc(buf_len, GFP_NOFS); @@ -323,6 +334,7 @@ char *tomoyo_realpath_nofollow(const char *pathname) if (pathname && kern_path(pathname, 0, &path) == 0) { char *buf = tomoyo_realpath_from_path(&path); + path_put(&path); return buf; } |