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>
18 * tomoyo_encode: Convert binary string to ascii string.
20 * @buffer: Buffer for ASCII string.
21 * @buflen: Size of @buffer.
22 * @str: Binary string.
24 * Returns 0 on success, -ENOMEM otherwise.
26 int tomoyo_encode(char *buffer, int buflen, const char *str)
29 const unsigned char c = *(unsigned char *) str++;
31 if (tomoyo_is_valid(c)) {
52 *buffer++ = (c >> 6) + '0';
53 *buffer++ = ((c >> 3) & 7) + '0';
54 *buffer++ = (c & 7) + '0';
60 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
62 * @path: Pointer to "struct path".
63 * @newname: Pointer to buffer to return value in.
64 * @newname_len: Size of @newname.
66 * Returns 0 on success, negative value otherwise.
68 * If dentry is a directory, trailing '/' is appended.
69 * Characters out of 0x20 < c < 0x7F range are converted to
70 * \ooo style octal string.
71 * Character \ is converted to \\ string.
73 int tomoyo_realpath_from_path2(struct path *path, char *newname,
77 struct dentry *dentry = path->dentry;
80 if (!dentry || !path->mnt || !newname || newname_len <= 2048)
82 if (dentry->d_op && dentry->d_op->d_dname) {
83 /* For "socket:[\$]" and "pipe:[\$]". */
84 static const int offset = 1536;
85 sp = dentry->d_op->d_dname(dentry, newname + offset,
86 newname_len - offset);
88 struct path ns_root = {.mnt = NULL, .dentry = NULL};
90 spin_lock(&dcache_lock);
91 /* go to whatever namespace root we are under */
92 sp = __d_path(path, &ns_root, newname, newname_len);
93 spin_unlock(&dcache_lock);
94 /* Prepend "/proc" prefix if using internal proc vfs mount. */
95 if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
96 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
99 memcpy(sp, "/proc", 5);
101 sp = ERR_PTR(-ENOMEM);
107 error = tomoyo_encode(newname, sp - newname, sp);
108 /* Append trailing '/' if dentry is a directory. */
109 if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
111 sp = newname + strlen(newname);
112 if (*(sp - 1) != '/') {
113 if (sp < newname + newname_len - 4) {
122 tomoyo_warn_oom(__func__);
127 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
129 * @path: Pointer to "struct path".
131 * Returns the realpath of the given @path on success, NULL otherwise.
133 * These functions use kzalloc(), so the caller must call kfree()
134 * if these functions didn't return NULL.
136 char *tomoyo_realpath_from_path(struct path *path)
138 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
140 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
141 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
142 <= TOMOYO_MAX_PATHNAME_LEN - 1);
145 if (tomoyo_realpath_from_path2(path, buf,
146 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
153 * tomoyo_realpath - Get realpath of a pathname.
155 * @pathname: The pathname to solve.
157 * Returns the realpath of @pathname on success, NULL otherwise.
159 char *tomoyo_realpath(const char *pathname)
163 if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
164 char *buf = tomoyo_realpath_from_path(&path);
172 * tomoyo_realpath_nofollow - Get realpath of a pathname.
174 * @pathname: The pathname to solve.
176 * Returns the realpath of @pathname on success, NULL otherwise.
178 char *tomoyo_realpath_nofollow(const char *pathname)
182 if (pathname && kern_path(pathname, 0, &path) == 0) {
183 char *buf = tomoyo_realpath_from_path(&path);