diff options
Diffstat (limited to 'security/tomoyo/realpath.c')
| -rw-r--r-- | security/tomoyo/realpath.c | 58 |
1 files changed, 19 insertions, 39 deletions
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 6ff8c21e4fff..1c483ee7f93d 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -7,6 +7,7 @@ #include "common.h" #include <linux/magic.h> +#include <linux/proc_fs.h> /** * tomoyo_encode2 - Encode binary string to ascii string. @@ -94,11 +95,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 +126,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,14 +155,17 @@ 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); + struct pid_namespace *proc_pidns = proc_pid_ns(sb); + if (*ep == '/' && pid && pid == - task_tgid_nr_ns(current, sb->s_fs_info)) { + task_tgid_nr_ns(current, proc_pidns)) { pos = ep - 5; if (pos < buffer) goto out; @@ -170,6 +178,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 +191,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 +207,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; @@ -209,31 +220,6 @@ out: } /** - * tomoyo_get_socket_name - Get the name of a socket. - * - * @path: Pointer to "struct path". - * @buffer: Pointer to buffer to return value in. - * @buflen: Sizeof @buffer. - * - * Returns the buffer. - */ -static char *tomoyo_get_socket_name(const struct path *path, char * const buffer, - const int buflen) -{ - 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); - } else { - snprintf(buffer, buflen, "socket:[unknown]"); - } - return buffer; -} - -/** * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root. * * @path: Pointer to "struct path". @@ -254,13 +240,12 @@ char *tomoyo_realpath_from_path(const struct path *path) char *name = NULL; unsigned int buf_len = PAGE_SIZE / 2; struct dentry *dentry = path->dentry; - struct super_block *sb; - if (!dentry) - return NULL; - sb = dentry->d_sb; + struct super_block *sb = dentry->d_sb; + while (1) { char *pos; struct inode *inode; + buf_len <<= 1; kfree(buf); buf = kmalloc(buf_len, GFP_NOFS); @@ -268,12 +253,7 @@ char *tomoyo_realpath_from_path(const struct path *path) break; /* To make sure that pos is '\0' terminated. */ buf[buf_len - 1] = '\0'; - /* Get better name for socket. */ - if (sb->s_magic == SOCKFS_MAGIC) { - pos = tomoyo_get_socket_name(path, buf, buf_len - 1); - goto encode; - } - /* For "pipe:[\$]". */ + /* For "pipe:[\$]" and "socket:[\$]". */ if (dentry->d_op && dentry->d_op->d_dname) { pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1); goto encode; @@ -281,10 +261,9 @@ char *tomoyo_realpath_from_path(const struct path *path) inode = d_backing_inode(sb->s_root); /* * Get local name for filesystems without rename() operation - * or dentry without vfsmount. */ - if (!path->mnt || - (!inode->i_op->rename)) + if ((!inode->i_op->rename && + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) pos = tomoyo_get_local_path(path->dentry, buf, buf_len - 1); /* Get absolute name for the rest. */ @@ -323,6 +302,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; } |
