2
* AppArmor security module
4
* This file contains AppArmor function for pathnames
6
* Copyright (C) 1998-2008 Novell/SUSE
7
* Copyright 2009 Canonical Ltd.
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License as
11
* published by the Free Software Foundation, version 2 of the
15
#include <linux/mnt_namespace.h>
16
#include <linux/mount.h>
17
#include <linux/namei.h>
18
#include <linux/path.h>
19
#include <linux/sched.h>
20
#include <linux/slab.h>
21
#include <linux/fs_struct.h>
23
#include "include/apparmor.h"
24
#include "include/path.h"
26
int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
29
int error = d_namespace_path(path, buffer, size - is_dir, name);
31
if (!error && is_dir && (*name)[1] != '\0')
33
* Append "/" to the pathname. The root directory is a special
34
* case; it already ends in slash.
36
strcpy(&buffer[size - 2], "/");
42
* aa_get_name - compute the pathname of a file
43
* @path: path the file
44
* @is_dir: set if the file is a directory
45
* @buffer: buffer that aa_get_name() allocated
46
* @name: the error code indicating whether aa_get_name failed
48
* Returns an error code if the there was a failure in obtaining the
51
* @name is apointer to the beginning of the pathname (which usually differs
52
* from the beginning of the buffer), or NULL. If there is an error @name
53
* may contain a partial or invalid name (in the case of a deleted file), that
54
* can be used for audit purposes, but it can not be used for mediation.
56
* We need @is_dir to indicate whether the file is a directory or not because
57
* the file may not yet exist, and so we cannot check the inode's file type.
59
int aa_get_name(struct path *path, int is_dir, char **buffer, char **name)
61
char *buf, *str = NULL;
68
buf = kmalloc(size, GFP_KERNEL);
72
error = aa_get_name_to_buffer(path, is_dir, buf, size, &str);
73
if (!error || (error == -ENOENT) || (error == -ESTALE))
78
if (size > g_apparmor_path_max)
87
int d_namespace_path(struct path *path, char *buf, int buflen, char **name)
89
struct path root, tmp, ns_root = { };
93
read_lock(¤t->fs->lock);
94
root = current->fs->root;
95
path_get(¤t->fs->root);
96
read_unlock(¤t->fs->lock);
97
spin_lock(&vfsmount_lock);
98
if (root.mnt && root.mnt->mnt_ns)
99
ns_root.mnt = mntget(root.mnt->mnt_ns->root);
101
ns_root.dentry = dget(ns_root.mnt->mnt_root);
102
spin_unlock(&vfsmount_lock);
103
spin_lock(&dcache_lock);
105
res = __d_path(path, &tmp, buf, buflen);
108
/* handle error conditions - and still allow a partial path to
111
error = PTR_ERR(res);
113
} else if (d_unhashed(path->dentry) && !path->dentry->d_inode) {
114
/* On some filesystems, newly allocated dentries appear
115
* to the security_path hooks as a deleted
116
* dentry except without an inode allocated.
118
* Remove the appended deleted text and return as a
119
* string for normal mediation. The (deleted) string
120
* is guarenteed to be added in this case, so just
123
buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
124
} else if (d_unhashed(path->dentry) && (buf + buflen) - res > 11 &&
125
strcmp(buf + buflen - 11, " (deleted)") == 0) {
126
/* For now allow mediation of deleted paths */
127
buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
128
} else if (!IS_ROOT(path->dentry) && d_unhashed(path->dentry)) {
131
} else if (tmp.dentry != ns_root.dentry && tmp.mnt != ns_root.mnt) {
132
/* disconnected path don return pathname starting with '/' */
139
spin_unlock(&dcache_lock);
146
char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
154
int namelen = strlen(table->procname);
156
if (buflen < namelen + 1)
158
buflen -= namelen + 1;
160
memcpy(buffer, table->procname, namelen);
162
table = table->parent;
167
memcpy(buffer, "/sys", 4);