0001
0002
0003
0004
0005
0006
0007
0008 #include "common.h"
0009 #include <linux/magic.h>
0010 #include <linux/proc_fs.h>
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 char *tomoyo_encode2(const char *str, int str_len)
0024 {
0025 int i;
0026 int len = 0;
0027 const char *p = str;
0028 char *cp;
0029 char *cp0;
0030
0031 if (!p)
0032 return NULL;
0033 for (i = 0; i < str_len; i++) {
0034 const unsigned char c = p[i];
0035
0036 if (c == '\\')
0037 len += 2;
0038 else if (c > ' ' && c < 127)
0039 len++;
0040 else
0041 len += 4;
0042 }
0043 len++;
0044
0045 cp = kzalloc(len + 10, GFP_NOFS);
0046 if (!cp)
0047 return NULL;
0048 cp0 = cp;
0049 p = str;
0050 for (i = 0; i < str_len; i++) {
0051 const unsigned char c = p[i];
0052
0053 if (c == '\\') {
0054 *cp++ = '\\';
0055 *cp++ = '\\';
0056 } else if (c > ' ' && c < 127) {
0057 *cp++ = c;
0058 } else {
0059 *cp++ = '\\';
0060 *cp++ = (c >> 6) + '0';
0061 *cp++ = ((c >> 3) & 7) + '0';
0062 *cp++ = (c & 7) + '0';
0063 }
0064 }
0065 return cp0;
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 char *tomoyo_encode(const char *str)
0079 {
0080 return str ? tomoyo_encode2(str, strlen(str)) : NULL;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer,
0095 const int buflen)
0096 {
0097 char *pos = ERR_PTR(-ENOMEM);
0098
0099 if (buflen >= 256) {
0100
0101 pos = d_absolute_path(path, buffer, buflen - 1);
0102 if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
0103 struct inode *inode = d_backing_inode(path->dentry);
0104
0105 if (inode && S_ISDIR(inode->i_mode)) {
0106 buffer[buflen - 2] = '/';
0107 buffer[buflen - 1] = '\0';
0108 }
0109 }
0110 }
0111 return pos;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
0126 const int buflen)
0127 {
0128 char *pos = ERR_PTR(-ENOMEM);
0129
0130 if (buflen >= 256) {
0131 pos = dentry_path_raw(dentry, buffer, buflen - 1);
0132 if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
0133 struct inode *inode = d_backing_inode(dentry);
0134
0135 if (inode && S_ISDIR(inode->i_mode)) {
0136 buffer[buflen - 2] = '/';
0137 buffer[buflen - 1] = '\0';
0138 }
0139 }
0140 }
0141 return pos;
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
0154 const int buflen)
0155 {
0156 struct super_block *sb = dentry->d_sb;
0157 char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen);
0158
0159 if (IS_ERR(pos))
0160 return pos;
0161
0162 if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
0163 char *ep;
0164 const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
0165 struct pid_namespace *proc_pidns = proc_pid_ns(sb);
0166
0167 if (*ep == '/' && pid && pid ==
0168 task_tgid_nr_ns(current, proc_pidns)) {
0169 pos = ep - 5;
0170 if (pos < buffer)
0171 goto out;
0172 memmove(pos, "/self", 5);
0173 }
0174 goto prepend_filesystem_name;
0175 }
0176
0177 if (!MAJOR(sb->s_dev))
0178 goto prepend_filesystem_name;
0179 {
0180 struct inode *inode = d_backing_inode(sb->s_root);
0181
0182
0183
0184
0185
0186 if (!inode->i_op->rename)
0187 goto prepend_filesystem_name;
0188 }
0189
0190 {
0191 char name[64];
0192 int name_len;
0193 const dev_t dev = sb->s_dev;
0194
0195 name[sizeof(name) - 1] = '\0';
0196 snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
0197 MINOR(dev));
0198 name_len = strlen(name);
0199 pos -= name_len;
0200 if (pos < buffer)
0201 goto out;
0202 memmove(pos, name, name_len);
0203 return pos;
0204 }
0205
0206 prepend_filesystem_name:
0207 {
0208 const char *name = sb->s_type->name;
0209 const int name_len = strlen(name);
0210
0211 pos -= name_len + 1;
0212 if (pos < buffer)
0213 goto out;
0214 memmove(pos, name, name_len);
0215 pos[name_len] = ':';
0216 }
0217 return pos;
0218 out:
0219 return ERR_PTR(-ENOMEM);
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 char *tomoyo_realpath_from_path(const struct path *path)
0238 {
0239 char *buf = NULL;
0240 char *name = NULL;
0241 unsigned int buf_len = PAGE_SIZE / 2;
0242 struct dentry *dentry = path->dentry;
0243 struct super_block *sb;
0244
0245 if (!dentry)
0246 return NULL;
0247 sb = dentry->d_sb;
0248 while (1) {
0249 char *pos;
0250 struct inode *inode;
0251
0252 buf_len <<= 1;
0253 kfree(buf);
0254 buf = kmalloc(buf_len, GFP_NOFS);
0255 if (!buf)
0256 break;
0257
0258 buf[buf_len - 1] = '\0';
0259
0260 if (dentry->d_op && dentry->d_op->d_dname) {
0261 pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
0262 goto encode;
0263 }
0264 inode = d_backing_inode(sb->s_root);
0265
0266
0267
0268
0269 if (!path->mnt ||
0270 (!inode->i_op->rename &&
0271 !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
0272 pos = tomoyo_get_local_path(path->dentry, buf,
0273 buf_len - 1);
0274
0275 else {
0276 pos = tomoyo_get_absolute_path(path, buf, buf_len - 1);
0277
0278
0279
0280
0281 if (pos == ERR_PTR(-EINVAL))
0282 pos = tomoyo_get_local_path(path->dentry, buf,
0283 buf_len - 1);
0284 }
0285 encode:
0286 if (IS_ERR(pos))
0287 continue;
0288 name = tomoyo_encode(pos);
0289 break;
0290 }
0291 kfree(buf);
0292 if (!name)
0293 tomoyo_warn_oom(__func__);
0294 return name;
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304 char *tomoyo_realpath_nofollow(const char *pathname)
0305 {
0306 struct path path;
0307
0308 if (pathname && kern_path(pathname, 0, &path) == 0) {
0309 char *buf = tomoyo_realpath_from_path(&path);
0310
0311 path_put(&path);
0312 return buf;
0313 }
0314 return NULL;
0315 }