]> git.karo-electronics.de Git - karo-tx-linux.git/blob - security/tomoyo/realpath.c
1fd685a94ad1243c0c162df511cb5d61e010e789
[karo-tx-linux.git] / security / tomoyo / realpath.c
1 /*
2  * security/tomoyo/realpath.c
3  *
4  * Pathname calculation functions for TOMOYO.
5  *
6  * Copyright (C) 2005-2010  NTT DATA CORPORATION
7  */
8
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>
15 #include "common.h"
16
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  */
26 int 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  */
73 int 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 {
88                 struct path ns_root = {.mnt = NULL, .dentry = NULL};
89
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)) {
97                         sp -= 5;
98                         if (sp >= newname)
99                                 memcpy(sp, "/proc", 5);
100                         else
101                                 sp = ERR_PTR(-ENOMEM);
102                 }
103         }
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)
122                 tomoyo_warn_oom(__func__);
123         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  *
133  * These functions use kzalloc(), so the caller must call kfree()
134  * if these functions didn't return NULL.
135  */
136 char *tomoyo_realpath_from_path(struct path *path)
137 {
138         char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
139
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);
143         if (!buf)
144                 return NULL;
145         if (tomoyo_realpath_from_path2(path, buf,
146                                        TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
147                 return buf;
148         kfree(buf);
149         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  */
159 char *tomoyo_realpath(const char *pathname)
160 {
161         struct path path;
162
163         if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
164                 char *buf = tomoyo_realpath_from_path(&path);
165                 path_put(&path);
166                 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  */
178 char *tomoyo_realpath_nofollow(const char *pathname)
179 {
180         struct path path;
181
182         if (pathname && kern_path(pathname, 0, &path) == 0) {
183                 char *buf = tomoyo_realpath_from_path(&path);
184                 path_put(&path);
185                 return buf;
186         }
187         return NULL;
188 }