2 * security/tomoyo/realpath.c
4 * Pathname calculation functions for TOMOYO.
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
9 #include <linux/types.h>
10 #include <linux/mount.h>
11 #include <linux/mnt_namespace.h>
12 #include <linux/fs_struct.h>
13 #include <linux/magic.h>
14 #include <linux/slab.h>
19 * tomoyo_encode: Convert binary string to ascii string.
21 * @str: String in binary format.
23 * Returns pointer to @str in ascii format on success, NULL otherwise.
25 * This function uses kzalloc(), so caller must kfree() if this function
28 char *tomoyo_encode(const char *str)
38 const unsigned char c = *p++;
41 else if (c > ' ' && c < 127)
47 /* Reserve space for appending "/". */
48 cp = kzalloc(len + 10, GFP_NOFS);
54 const unsigned char c = *p++;
59 } else if (c > ' ' && c < 127) {
63 *cp++ = (c >> 6) + '0';
64 *cp++ = ((c >> 3) & 7) + '0';
65 *cp++ = (c & 7) + '0';
72 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
74 * @path: Pointer to "struct path".
76 * Returns the realpath of the given @path on success, NULL otherwise.
78 * If dentry is a directory, trailing '/' is appended.
79 * Characters out of 0x20 < c < 0x7F range are converted to
80 * \ooo style octal string.
81 * Character \ is converted to \\ string.
83 * These functions use kzalloc(), so the caller must call kfree()
84 * if these functions didn't return NULL.
86 char *tomoyo_realpath_from_path(struct path *path)
90 unsigned int buf_len = PAGE_SIZE / 2;
91 struct dentry *dentry = path->dentry;
95 is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode);
97 struct path ns_root = { .mnt = NULL, .dentry = NULL };
101 buf = kmalloc(buf_len, GFP_NOFS);
104 /* Get better name for socket. */
105 if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) {
106 struct inode *inode = dentry->d_inode;
107 struct socket *sock = inode ? SOCKET_I(inode) : NULL;
108 struct sock *sk = sock ? sock->sk : NULL;
110 snprintf(buf, buf_len - 1, "socket:[family=%u:"
111 "type=%u:protocol=%u]", sk->sk_family,
112 sk->sk_type, sk->sk_protocol);
114 snprintf(buf, buf_len - 1, "socket:[unknown]");
116 name = tomoyo_encode(buf);
119 /* For "socket:[\$]" and "pipe:[\$]". */
120 if (dentry->d_op && dentry->d_op->d_dname) {
121 pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
124 name = tomoyo_encode(pos);
127 /* If we don't have a vfsmount, we can't calculate. */
130 spin_lock(&dcache_lock);
131 /* go to whatever namespace root we are under */
132 pos = __d_path(path, &ns_root, buf, buf_len);
133 spin_unlock(&dcache_lock);
134 /* Prepend "/proc" prefix if using internal proc vfs mount. */
135 if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
136 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
139 memcpy(pos, "/proc", 5);
141 pos = ERR_PTR(-ENOMEM);
145 name = tomoyo_encode(pos);
150 tomoyo_warn_oom(__func__);
151 else if (is_dir && *name) {
152 /* Append trailing '/' if dentry is a directory. */
153 char *pos = name + strlen(name) - 1;
156 * This is OK because tomoyo_encode() reserves space
165 * tomoyo_realpath_nofollow - Get realpath of a pathname.
167 * @pathname: The pathname to solve.
169 * Returns the realpath of @pathname on success, NULL otherwise.
171 char *tomoyo_realpath_nofollow(const char *pathname)
175 if (pathname && kern_path(pathname, 0, &path) == 0) {
176 char *buf = tomoyo_realpath_from_path(&path);