blob: 1fd685a94ad1243c0c162df511cb5d61e010e789 [file] [log] [blame]
Kentaro Takedac73bd6d2009-02-05 17:18:12 +09001/*
2 * security/tomoyo/realpath.c
3 *
Tetsuo Handac3ef1502010-05-17 10:12:46 +09004 * Pathname calculation functions for TOMOYO.
Kentaro Takedac73bd6d2009-02-05 17:18:12 +09005 *
Tetsuo Handac3ef1502010-05-17 10:12:46 +09006 * Copyright (C) 2005-2010 NTT DATA CORPORATION
Kentaro Takedac73bd6d2009-02-05 17:18:12 +09007 */
8
9#include <linux/types.h>
10#include <linux/mount.h>
11#include <linux/mnt_namespace.h>
Al Viro5ad4e532009-03-29 19:50:06 -040012#include <linux/fs_struct.h>
Tetsuo Handa67fa4882009-12-09 15:36:04 +090013#include <linux/magic.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090014#include <linux/slab.h>
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090015#include "common.h"
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090016
17/**
18 * tomoyo_encode: Convert binary string to ascii string.
19 *
20 * @buffer: Buffer for ASCII string.
21 * @buflen: Size of @buffer.
22 * @str: Binary string.
23 *
24 * Returns 0 on success, -ENOMEM otherwise.
25 */
26int tomoyo_encode(char *buffer, int buflen, const char *str)
27{
28 while (1) {
29 const unsigned char c = *(unsigned char *) str++;
30
31 if (tomoyo_is_valid(c)) {
32 if (--buflen <= 0)
33 break;
34 *buffer++ = (char) c;
35 if (c != '\\')
36 continue;
37 if (--buflen <= 0)
38 break;
39 *buffer++ = (char) c;
40 continue;
41 }
42 if (!c) {
43 if (--buflen <= 0)
44 break;
45 *buffer = '\0';
46 return 0;
47 }
48 buflen -= 4;
49 if (buflen <= 0)
50 break;
51 *buffer++ = '\\';
52 *buffer++ = (c >> 6) + '0';
53 *buffer++ = ((c >> 3) & 7) + '0';
54 *buffer++ = (c & 7) + '0';
55 }
56 return -ENOMEM;
57}
58
59/**
60 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
61 *
62 * @path: Pointer to "struct path".
63 * @newname: Pointer to buffer to return value in.
64 * @newname_len: Size of @newname.
65 *
66 * Returns 0 on success, negative value otherwise.
67 *
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.
72 */
73int tomoyo_realpath_from_path2(struct path *path, char *newname,
74 int newname_len)
75{
76 int error = -ENOMEM;
77 struct dentry *dentry = path->dentry;
78 char *sp;
79
80 if (!dentry || !path->mnt || !newname || newname_len <= 2048)
81 return -EINVAL;
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);
87 } else {
Al Viro37afdc72010-02-05 01:41:33 -050088 struct path ns_root = {.mnt = NULL, .dentry = NULL};
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090089
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090090 spin_lock(&dcache_lock);
Al Viro37afdc72010-02-05 01:41:33 -050091 /* go to whatever namespace root we are under */
92 sp = __d_path(path, &ns_root, newname, newname_len);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090093 spin_unlock(&dcache_lock);
Eric W. Biedermana4054b62009-11-20 09:12:22 -080094 /* Prepend "/proc" prefix if using internal proc vfs mount. */
Al Viro440b3c62010-02-05 09:37:21 -050095 if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
Tetsuo Handa67fa4882009-12-09 15:36:04 +090096 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
Eric W. Biedermana4054b62009-11-20 09:12:22 -080097 sp -= 5;
98 if (sp >= newname)
99 memcpy(sp, "/proc", 5);
100 else
101 sp = ERR_PTR(-ENOMEM);
102 }
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900103 }
104 if (IS_ERR(sp))
105 error = PTR_ERR(sp);
106 else
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)
110 && *newname) {
111 sp = newname + strlen(newname);
112 if (*(sp - 1) != '/') {
113 if (sp < newname + newname_len - 4) {
114 *sp++ = '/';
115 *sp = '\0';
116 } else {
117 error = -ENOMEM;
118 }
119 }
120 }
121 if (error)
Tetsuo Handac3ef1502010-05-17 10:12:46 +0900122 tomoyo_warn_oom(__func__);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900123 return error;
124}
125
126/**
127 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
128 *
129 * @path: Pointer to "struct path".
130 *
131 * Returns the realpath of the given @path on success, NULL otherwise.
132 *
Tetsuo Handa8e2d39a2010-01-26 20:45:27 +0900133 * These functions use kzalloc(), so the caller must call kfree()
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900134 * if these functions didn't return NULL.
135 */
136char *tomoyo_realpath_from_path(struct path *path)
137{
Tetsuo Handa4e5d6f72010-04-28 14:17:42 +0900138 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900139
Tetsuo Handac3ef1502010-05-17 10:12:46 +0900140 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900141 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
142 <= TOMOYO_MAX_PATHNAME_LEN - 1);
143 if (!buf)
144 return NULL;
145 if (tomoyo_realpath_from_path2(path, buf,
146 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
147 return buf;
Tetsuo Handa8e2d39a2010-01-26 20:45:27 +0900148 kfree(buf);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900149 return NULL;
150}
151
152/**
153 * tomoyo_realpath - Get realpath of a pathname.
154 *
155 * @pathname: The pathname to solve.
156 *
157 * Returns the realpath of @pathname on success, NULL otherwise.
158 */
159char *tomoyo_realpath(const char *pathname)
160{
Al Viroe24977d2009-04-02 21:17:03 -0400161 struct path path;
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900162
Al Viroe24977d2009-04-02 21:17:03 -0400163 if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
164 char *buf = tomoyo_realpath_from_path(&path);
165 path_put(&path);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900166 return buf;
167 }
168 return NULL;
169}
170
171/**
172 * tomoyo_realpath_nofollow - Get realpath of a pathname.
173 *
174 * @pathname: The pathname to solve.
175 *
176 * Returns the realpath of @pathname on success, NULL otherwise.
177 */
178char *tomoyo_realpath_nofollow(const char *pathname)
179{
Al Viroe24977d2009-04-02 21:17:03 -0400180 struct path path;
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900181
Al Viroe24977d2009-04-02 21:17:03 -0400182 if (pathname && kern_path(pathname, 0, &path) == 0) {
183 char *buf = tomoyo_realpath_from_path(&path);
184 path_put(&path);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900185 return buf;
186 }
187 return NULL;
188}