^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * security/tomoyo/realpath.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005-2011 NTT DATA CORPORATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/magic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * tomoyo_encode2 - Encode binary string to ascii string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * @str: String in binary format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * @str_len: Size of @str in byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Returns pointer to @str in ascii format on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * This function uses kzalloc(), so caller must kfree() if this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * didn't return NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) char *tomoyo_encode2(const char *str, int str_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) const char *p = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) char *cp0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) for (i = 0; i < str_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) const unsigned char c = p[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (c == '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) len += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) else if (c > ' ' && c < 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Reserve space for appending "/". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) cp = kzalloc(len + 10, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) cp0 = cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) p = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) for (i = 0; i < str_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const unsigned char c = p[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (c == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *cp++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *cp++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) } else if (c > ' ' && c < 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *cp++ = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *cp++ = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *cp++ = (c >> 6) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *cp++ = ((c >> 3) & 7) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *cp++ = (c & 7) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return cp0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * tomoyo_encode - Encode binary string to ascii string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @str: String in binary format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Returns pointer to @str in ascii format on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * This function uses kzalloc(), so caller must kfree() if this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * didn't return NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) char *tomoyo_encode(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return str ? tomoyo_encode2(str, strlen(str)) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @path: Pointer to "struct path".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @buffer: Pointer to buffer to return value in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @buflen: Sizeof @buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Returns the buffer on success, an error code otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * If dentry is a directory, trailing '/' is appended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) char *pos = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (buflen >= 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* go to whatever namespace root we are under */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pos = d_absolute_path(path, buffer, buflen - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct inode *inode = d_backing_inode(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (inode && S_ISDIR(inode->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) buffer[buflen - 2] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) buffer[buflen - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * tomoyo_get_dentry_path - Get the path of a dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @dentry: Pointer to "struct dentry".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @buffer: Pointer to buffer to return value in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @buflen: Sizeof @buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Returns the buffer on success, an error code otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * If dentry is a directory, trailing '/' is appended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) char *pos = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (buflen >= 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pos = dentry_path_raw(dentry, buffer, buflen - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct inode *inode = d_backing_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (inode && S_ISDIR(inode->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) buffer[buflen - 2] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) buffer[buflen - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * tomoyo_get_local_path - Get the path of a dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @dentry: Pointer to "struct dentry".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @buffer: Pointer to buffer to return value in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @buflen: Sizeof @buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * Returns the buffer on success, an error code otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) const int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct super_block *sb = dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (IS_ERR(pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Convert from $PID to self if $PID is current thread. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) char *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct pid_namespace *proc_pidns = proc_pid_ns(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (*ep == '/' && pid && pid ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) task_tgid_nr_ns(current, proc_pidns)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) pos = ep - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (pos < buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) memmove(pos, "/self", 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) goto prepend_filesystem_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* Use filesystem name for unnamed devices. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!MAJOR(sb->s_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) goto prepend_filesystem_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct inode *inode = d_backing_inode(sb->s_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Use filesystem name if filesystem does not support rename()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!inode->i_op->rename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto prepend_filesystem_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Prepend device name. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) char name[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const dev_t dev = sb->s_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) name[sizeof(name) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) MINOR(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) name_len = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pos -= name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (pos < buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) memmove(pos, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Prepend filesystem name. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) prepend_filesystem_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const char *name = sb->s_type->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) const int name_len = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pos -= name_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (pos < buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) memmove(pos, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) pos[name_len] = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @path: Pointer to "struct path".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Returns the realpath of the given @path on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * If dentry is a directory, trailing '/' is appended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * Characters out of 0x20 < c < 0x7F range are converted to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * \ooo style octal string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * Character \ is converted to \\ string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * These functions use kzalloc(), so the caller must call kfree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * if these functions didn't return NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) char *tomoyo_realpath_from_path(const struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) char *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned int buf_len = PAGE_SIZE / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct dentry *dentry = path->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) sb = dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) char *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) buf_len <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) buf = kmalloc(buf_len, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* To make sure that pos is '\0' terminated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) buf[buf_len - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* For "pipe:[\$]" and "socket:[\$]". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (dentry->d_op && dentry->d_op->d_dname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) goto encode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) inode = d_backing_inode(sb->s_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Get local name for filesystems without rename() operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * or dentry without vfsmount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!path->mnt ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) (!inode->i_op->rename &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pos = tomoyo_get_local_path(path->dentry, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) buf_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Get absolute name for the rest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pos = tomoyo_get_absolute_path(path, buf, buf_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * Fall back to local name if absolute name is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (pos == ERR_PTR(-EINVAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pos = tomoyo_get_local_path(path->dentry, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) buf_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) encode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (IS_ERR(pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) name = tomoyo_encode(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) tomoyo_warn_oom(__func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * tomoyo_realpath_nofollow - Get realpath of a pathname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @pathname: The pathname to solve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Returns the realpath of @pathname on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) char *tomoyo_realpath_nofollow(const char *pathname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (pathname && kern_path(pathname, 0, &path) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) char *buf = tomoyo_realpath_from_path(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }