void *prlfs_get_path(struct dentry *dentry, void *buf, int *plen) { int len; char *p; DPRINTK("ENTER\n"); len = *plen; p = buf; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) if ((dentry->d_name.len > NAME_MAX) || (len < 2)) { p = ERR_PTR(-ENAMETOOLONG); goto out; } p += --len; *p = '\0'; spin_lock(&dcache_lock); while (!IS_ROOT(dentry)) { int nlen; struct dentry *parent; parent = dentry->d_parent; prefetch(parent); nlen = dentry->d_name.len; if (len < nlen + 1) { p = ERR_PTR(-ENAMETOOLONG); goto out_lock; } len -= nlen + 1; p -= nlen; memcpy(p, dentry->d_name.name, nlen); *(--p) = '/'; dentry = parent; } if (*p != '/') { *(--p) = '/'; --len; } out_lock: spin_unlock(&dcache_lock); if (!IS_ERR(p)) *plen -= len; out: #else p = dentry_path_raw(dentry, p, len); *plen = strnlen(p, PAGE_SIZE-1) + 1; #endif DPRINTK("EXIT returning %p\n", p); return p; }
/** * tomoyo_get_dentry_path - Get the path of a dentry. * * @dentry: Pointer to "struct dentry". * @buffer: Pointer to buffer to return value in. * @buflen: Sizeof @buffer. * * Returns the buffer on success, an error code otherwise. * * If dentry is a directory, trailing '/' is appended. */ static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer, const int buflen) { char *pos = ERR_PTR(-ENOMEM); if (buflen >= 256) { pos = dentry_path_raw(dentry, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = dentry->d_inode; if (inode && S_ISDIR(inode->i_mode)) { buffer[buflen - 2] = '/'; buffer[buflen - 1] = '\0'; } } } return pos; }
/* * Function that takes in a file desc * And checks recursively if any of its parent * is under watch * Also takes the int bMap which specifies what changes * were made */ void process_file_desc(unsigned int fd, int *bMap) { unsigned long parentInodeNo; struct file *curFile = NULL; char *path = NULL; char *path_buf = NULL; if (fd < 3) { goto OUT; } curFile = fget(fd); if (!curFile) { curFile = NULL; goto OUT; } path_buf = kmalloc(_MAX_PATH_LEN_, GFP_KERNEL); if (path_buf == NULL) { goto OUT; } path = dentry_path_raw(curFile->f_path.dentry, path_buf, _MAX_PATH_LEN_); if (NULL != path) { if (path_filter(path)) { goto OUT; } } parentInodeNo = check_if_any_parent_is_watched_filp(curFile); if (parentInodeNo > 0) { add_data_to_obj(parentInodeNo, curFile->f_path.dentry->d_inode->i_ino, bMap); } OUT: if (curFile) { fput(curFile); curFile = NULL; } if (path_buf) { kfree(path_buf); path_buf = NULL; } }
/** * ccs_get_dentry_path - Get the path of a dentry. * * @dentry: Pointer to "struct dentry". * @buffer: Pointer to buffer to return value in. * @buflen: Sizeof @buffer. * * Returns the buffer on success, an error code otherwise. * * Based on dentry_path() in fs/dcache.c * * If dentry is a directory, trailing '/' is appended. */ static char *ccs_get_dentry_path(struct dentry *dentry, char * const buffer, const int buflen) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) char *pos = ERR_PTR(-ENOMEM); if (buflen >= 256) { /* rename_lock is locked/unlocked by dentry_path_raw(). */ pos = dentry_path_raw(dentry, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = dentry->d_inode; if (inode && S_ISDIR(inode->i_mode)) { buffer[buflen - 2] = '/'; buffer[buflen - 1] = '\0'; } } } return pos; #else char *pos = buffer + buflen - 1; if (buflen < 256) return ERR_PTR(-ENOMEM); *pos = '\0'; if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) *--pos = '/'; spin_lock(&dcache_lock); while (!IS_ROOT(dentry)) { struct dentry *parent = dentry->d_parent; const char *name = dentry->d_name.name; const int len = dentry->d_name.len; pos -= len; if (pos <= buffer) { pos = ERR_PTR(-ENOMEM); break; } memmove(pos, name, len); *--pos = '/'; dentry = parent; } spin_unlock(&dcache_lock); return pos; #endif }
/** * d_namespace_path - lookup a name associated with a given path * @path: path to lookup (NOT NULL) * @buf: buffer to store path to (NOT NULL) * @buflen: length of @buf * @name: Returns - pointer for start of path name with in @buf (NOT NULL) * @flags: flags controlling path lookup * * Handle path name lookup. * * Returns: %0 else error code if path lookup fails * When no error the path name is returned in @name which points to * to a position in @buf */ static int d_namespace_path(struct path *path, char *buf, int buflen, char **name, int flags) { char *res; int error = 0; int connected = 1; if (path->mnt->mnt_flags & MNT_INTERNAL) { /* it's not mounted anywhere */ res = dentry_path(path->dentry, buf, buflen); *name = res; if (IS_ERR(res)) { *name = buf; return PTR_ERR(res); } if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC && strncmp(*name, "/sys/", 5) == 0) { /* TODO: convert over to using a per namespace * control instead of hard coded /proc */ return prepend(name, *name - buf, "/proc", 5); } return 0; } /* resolve paths relative to chroot?*/ if (flags & PATH_CHROOT_REL) { struct path root; get_fs_root(current->fs, &root); res = __d_path(path, &root, buf, buflen); path_put(&root); } else { res = d_absolute_path(path, buf, buflen); if (!our_mnt(path->mnt)) connected = 0; } /* handle error conditions - and still allow a partial path to * be returned. */ if (!res || IS_ERR(res)) { connected = 0; res = dentry_path_raw(path->dentry, buf, buflen); if (IS_ERR(res)) { error = PTR_ERR(res); *name = buf; goto out; }; } else if (!our_mnt(path->mnt)) connected = 0; *name = res; /* Handle two cases: * 1. A deleted dentry && profile is not allowing mediation of deleted * 2. On some filesystems, newly allocated dentries appear to the * security_path hooks as a deleted dentry except without an inode * allocated. */ if (d_unlinked(path->dentry) && path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { error = -ENOENT; goto out; } /* If the path is not connected to the expected root, * check if it is a sysctl and handle specially else remove any * leading / that __d_path may have returned. * Unless * specifically directed to connect the path, * OR * if in a chroot and doing chroot relative paths and the path * resolves to the namespace root (would be connected outside * of chroot) and specifically directed to connect paths to * namespace root. */ if (!connected) { if (!(flags & PATH_CONNECT_PATH) && !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && our_mnt(path->mnt))) { /* disconnected path, don't return pathname starting * with '/' */ error = -ESTALE; if (*res == '/') *name = res + 1; } } out: return error; }
static int dp_debugfs_init(struct data_path *dp) { char buf[256]; char path[256]; dp->dentry = debugfs_create_dir(dp->name ? dp->name : "dp", dp_debugfs_root_dir); if (!dp->dentry) return -ENOMEM; snprintf(path, sizeof(path), "../../../%s", dentry_path_raw(dp->rbctl->rbdir, buf, sizeof(buf))); if (IS_ERR_OR_NULL(debugfs_create_symlink( "shm", dp->dentry, path))) goto error; if (IS_ERR_OR_NULL(debugfs_create_file( "tx_q", S_IRUGO, dp->dentry, dp, &fops_tx_q))) goto error; if (IS_ERR_OR_NULL(debugfs_create_file( "stat", S_IRUGO, dp->dentry, dp, &fops_stat))) goto error; if (IS_ERR_OR_NULL(debugfs_create_file( "wm", S_IRUGO | S_IWUSR, dp->dentry, dp, &fops_wm))) goto error; if (IS_ERR_OR_NULL(debugfs_create_bool( "enable_piggyback", S_IRUGO | S_IWUSR, dp->dentry, &dp->enable_piggyback))) goto error; if (IS_ERR_OR_NULL(debugfs_create_bool( "is_tx_stopped", S_IRUGO | S_IWUSR, dp->dentry, &dp->is_tx_stopped))) goto error; if (IS_ERR_OR_NULL(debugfs_create_u32( "tx_q_max_len", S_IRUGO | S_IWUSR, dp->dentry, &dp->tx_q_max_len))) goto error; if (IS_ERR_OR_NULL(debugfs_create_u16( "max_tx_shots", S_IRUGO | S_IWUSR, dp->dentry, &dp->max_tx_shots))) goto error; if (IS_ERR_OR_NULL(debugfs_create_u16( "max_rx_shots", S_IRUGO | S_IWUSR, dp->dentry, &dp->max_rx_shots))) goto error; if (IS_ERR_OR_NULL(debugfs_create_u16( "tx_sched_delay_in_ms", S_IRUGO | S_IWUSR, dp->dentry, &dp->tx_sched_delay_in_ms))) goto error; if (IS_ERR_OR_NULL(debugfs_create_u16( "tx_q_min_sched_len", S_IRUGO | S_IWUSR, dp->dentry, &dp->tx_q_min_sched_len))) goto error; return 0; error: debugfs_remove_recursive(dp->dentry); dp->dentry = NULL; return -1; }