| .. | .. |
|---|
| 7 | 7 | |
|---|
| 8 | 8 | #include "common.h" |
|---|
| 9 | 9 | #include <linux/magic.h> |
|---|
| 10 | +#include <linux/proc_fs.h> |
|---|
| 10 | 11 | |
|---|
| 11 | 12 | /** |
|---|
| 12 | 13 | * tomoyo_encode2 - Encode binary string to ascii string. |
|---|
| .. | .. |
|---|
| 94 | 95 | const int buflen) |
|---|
| 95 | 96 | { |
|---|
| 96 | 97 | char *pos = ERR_PTR(-ENOMEM); |
|---|
| 98 | + |
|---|
| 97 | 99 | if (buflen >= 256) { |
|---|
| 98 | 100 | /* go to whatever namespace root we are under */ |
|---|
| 99 | 101 | pos = d_absolute_path(path, buffer, buflen - 1); |
|---|
| 100 | 102 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { |
|---|
| 101 | 103 | struct inode *inode = d_backing_inode(path->dentry); |
|---|
| 104 | + |
|---|
| 102 | 105 | if (inode && S_ISDIR(inode->i_mode)) { |
|---|
| 103 | 106 | buffer[buflen - 2] = '/'; |
|---|
| 104 | 107 | buffer[buflen - 1] = '\0'; |
|---|
| .. | .. |
|---|
| 123 | 126 | const int buflen) |
|---|
| 124 | 127 | { |
|---|
| 125 | 128 | char *pos = ERR_PTR(-ENOMEM); |
|---|
| 129 | + |
|---|
| 126 | 130 | if (buflen >= 256) { |
|---|
| 127 | 131 | pos = dentry_path_raw(dentry, buffer, buflen - 1); |
|---|
| 128 | 132 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { |
|---|
| 129 | 133 | struct inode *inode = d_backing_inode(dentry); |
|---|
| 134 | + |
|---|
| 130 | 135 | if (inode && S_ISDIR(inode->i_mode)) { |
|---|
| 131 | 136 | buffer[buflen - 2] = '/'; |
|---|
| 132 | 137 | buffer[buflen - 1] = '\0'; |
|---|
| .. | .. |
|---|
| 150 | 155 | { |
|---|
| 151 | 156 | struct super_block *sb = dentry->d_sb; |
|---|
| 152 | 157 | char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen); |
|---|
| 158 | + |
|---|
| 153 | 159 | if (IS_ERR(pos)) |
|---|
| 154 | 160 | return pos; |
|---|
| 155 | 161 | /* Convert from $PID to self if $PID is current thread. */ |
|---|
| 156 | 162 | if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { |
|---|
| 157 | 163 | char *ep; |
|---|
| 158 | 164 | const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); |
|---|
| 165 | + struct pid_namespace *proc_pidns = proc_pid_ns(sb); |
|---|
| 166 | + |
|---|
| 159 | 167 | if (*ep == '/' && pid && pid == |
|---|
| 160 | | - task_tgid_nr_ns(current, sb->s_fs_info)) { |
|---|
| 168 | + task_tgid_nr_ns(current, proc_pidns)) { |
|---|
| 161 | 169 | pos = ep - 5; |
|---|
| 162 | 170 | if (pos < buffer) |
|---|
| 163 | 171 | goto out; |
|---|
| .. | .. |
|---|
| 170 | 178 | goto prepend_filesystem_name; |
|---|
| 171 | 179 | { |
|---|
| 172 | 180 | struct inode *inode = d_backing_inode(sb->s_root); |
|---|
| 181 | + |
|---|
| 173 | 182 | /* |
|---|
| 174 | 183 | * Use filesystem name if filesystem does not support rename() |
|---|
| 175 | 184 | * operation. |
|---|
| .. | .. |
|---|
| 182 | 191 | char name[64]; |
|---|
| 183 | 192 | int name_len; |
|---|
| 184 | 193 | const dev_t dev = sb->s_dev; |
|---|
| 194 | + |
|---|
| 185 | 195 | name[sizeof(name) - 1] = '\0'; |
|---|
| 186 | 196 | snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev), |
|---|
| 187 | 197 | MINOR(dev)); |
|---|
| .. | .. |
|---|
| 197 | 207 | { |
|---|
| 198 | 208 | const char *name = sb->s_type->name; |
|---|
| 199 | 209 | const int name_len = strlen(name); |
|---|
| 210 | + |
|---|
| 200 | 211 | pos -= name_len + 1; |
|---|
| 201 | 212 | if (pos < buffer) |
|---|
| 202 | 213 | goto out; |
|---|
| .. | .. |
|---|
| 206 | 217 | return pos; |
|---|
| 207 | 218 | out: |
|---|
| 208 | 219 | return ERR_PTR(-ENOMEM); |
|---|
| 209 | | -} |
|---|
| 210 | | - |
|---|
| 211 | | -/** |
|---|
| 212 | | - * tomoyo_get_socket_name - Get the name of a socket. |
|---|
| 213 | | - * |
|---|
| 214 | | - * @path: Pointer to "struct path". |
|---|
| 215 | | - * @buffer: Pointer to buffer to return value in. |
|---|
| 216 | | - * @buflen: Sizeof @buffer. |
|---|
| 217 | | - * |
|---|
| 218 | | - * Returns the buffer. |
|---|
| 219 | | - */ |
|---|
| 220 | | -static char *tomoyo_get_socket_name(const struct path *path, char * const buffer, |
|---|
| 221 | | - const int buflen) |
|---|
| 222 | | -{ |
|---|
| 223 | | - struct inode *inode = d_backing_inode(path->dentry); |
|---|
| 224 | | - struct socket *sock = inode ? SOCKET_I(inode) : NULL; |
|---|
| 225 | | - struct sock *sk = sock ? sock->sk : NULL; |
|---|
| 226 | | - if (sk) { |
|---|
| 227 | | - snprintf(buffer, buflen, "socket:[family=%u:type=%u:" |
|---|
| 228 | | - "protocol=%u]", sk->sk_family, sk->sk_type, |
|---|
| 229 | | - sk->sk_protocol); |
|---|
| 230 | | - } else { |
|---|
| 231 | | - snprintf(buffer, buflen, "socket:[unknown]"); |
|---|
| 232 | | - } |
|---|
| 233 | | - return buffer; |
|---|
| 234 | 220 | } |
|---|
| 235 | 221 | |
|---|
| 236 | 222 | /** |
|---|
| .. | .. |
|---|
| 255 | 241 | unsigned int buf_len = PAGE_SIZE / 2; |
|---|
| 256 | 242 | struct dentry *dentry = path->dentry; |
|---|
| 257 | 243 | struct super_block *sb; |
|---|
| 244 | + |
|---|
| 258 | 245 | if (!dentry) |
|---|
| 259 | 246 | return NULL; |
|---|
| 260 | 247 | sb = dentry->d_sb; |
|---|
| 261 | 248 | while (1) { |
|---|
| 262 | 249 | char *pos; |
|---|
| 263 | 250 | struct inode *inode; |
|---|
| 251 | + |
|---|
| 264 | 252 | buf_len <<= 1; |
|---|
| 265 | 253 | kfree(buf); |
|---|
| 266 | 254 | buf = kmalloc(buf_len, GFP_NOFS); |
|---|
| .. | .. |
|---|
| 268 | 256 | break; |
|---|
| 269 | 257 | /* To make sure that pos is '\0' terminated. */ |
|---|
| 270 | 258 | buf[buf_len - 1] = '\0'; |
|---|
| 271 | | - /* Get better name for socket. */ |
|---|
| 272 | | - if (sb->s_magic == SOCKFS_MAGIC) { |
|---|
| 273 | | - pos = tomoyo_get_socket_name(path, buf, buf_len - 1); |
|---|
| 274 | | - goto encode; |
|---|
| 275 | | - } |
|---|
| 276 | | - /* For "pipe:[\$]". */ |
|---|
| 259 | + /* For "pipe:[\$]" and "socket:[\$]". */ |
|---|
| 277 | 260 | if (dentry->d_op && dentry->d_op->d_dname) { |
|---|
| 278 | 261 | pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1); |
|---|
| 279 | 262 | goto encode; |
|---|
| .. | .. |
|---|
| 284 | 267 | * or dentry without vfsmount. |
|---|
| 285 | 268 | */ |
|---|
| 286 | 269 | if (!path->mnt || |
|---|
| 287 | | - (!inode->i_op->rename)) |
|---|
| 270 | + (!inode->i_op->rename && |
|---|
| 271 | + !(sb->s_type->fs_flags & FS_REQUIRES_DEV))) |
|---|
| 288 | 272 | pos = tomoyo_get_local_path(path->dentry, buf, |
|---|
| 289 | 273 | buf_len - 1); |
|---|
| 290 | 274 | /* Get absolute name for the rest. */ |
|---|
| .. | .. |
|---|
| 323 | 307 | |
|---|
| 324 | 308 | if (pathname && kern_path(pathname, 0, &path) == 0) { |
|---|
| 325 | 309 | char *buf = tomoyo_realpath_from_path(&path); |
|---|
| 310 | + |
|---|
| 326 | 311 | path_put(&path); |
|---|
| 327 | 312 | return buf; |
|---|
| 328 | 313 | } |
|---|