~ubuntu-branches/ubuntu/karmic/linux-mvl-dove/karmic-proposed

« back to all changes in this revision

Viewing changes to ubuntu/apparmor/path.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bader
  • Date: 2010-03-10 22:24:12 UTC
  • mto: (15.1.2 karmic-security)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20100310222412-k86m3r53jw0je7x1
Tags: upstream-2.6.31
ImportĀ upstreamĀ versionĀ 2.6.31

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * AppArmor security module
3
 
 *
4
 
 * This file contains AppArmor function for pathnames
5
 
 *
6
 
 * Copyright (C) 1998-2008 Novell/SUSE
7
 
 * Copyright 2009 Canonical Ltd.
8
 
 *
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
12
 
 * License.
13
 
 */
14
 
 
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>
22
 
 
23
 
#include "include/apparmor.h"
24
 
#include "include/path.h"
25
 
 
26
 
int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
27
 
                          char **name)
28
 
{
29
 
        int error = d_namespace_path(path, buffer, size - is_dir, name);
30
 
 
31
 
        if (!error && is_dir && (*name)[1] != '\0')
32
 
                /*
33
 
                 * Append "/" to the pathname.  The root directory is a special
34
 
                 * case; it already ends in slash.
35
 
                 */
36
 
                strcpy(&buffer[size - 2], "/");
37
 
 
38
 
        return error;
39
 
}
40
 
 
41
 
/**
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
47
 
 *
48
 
 * Returns an error code if the there was a failure in obtaining the
49
 
 * name.
50
 
 *
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.
55
 
 *
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.
58
 
 */
59
 
int aa_get_name(struct path *path, int is_dir, char **buffer, char **name)
60
 
{
61
 
        char *buf, *str = NULL;
62
 
        int size = 256;
63
 
        int error;
64
 
 
65
 
        *name = NULL;
66
 
        *buffer = NULL;
67
 
        for (;;) {
68
 
                buf = kmalloc(size, GFP_KERNEL);
69
 
                if (!buf)
70
 
                        return -ENOMEM;
71
 
 
72
 
                error = aa_get_name_to_buffer(path, is_dir, buf, size, &str);
73
 
                if (!error || (error == -ENOENT) || (error == -ESTALE))
74
 
                        break;
75
 
 
76
 
                kfree(buf);
77
 
                size <<= 1;
78
 
                if (size > g_apparmor_path_max)
79
 
                        return -ENAMETOOLONG;
80
 
        }
81
 
        *buffer = buf;
82
 
        *name = str;
83
 
 
84
 
        return error;
85
 
}
86
 
 
87
 
int d_namespace_path(struct path *path, char *buf, int buflen, char **name)
88
 
{
89
 
        struct path root, tmp, ns_root = { };
90
 
        char *res;
91
 
        int error = 0;
92
 
 
93
 
        read_lock(&current->fs->lock);
94
 
        root = current->fs->root;
95
 
        path_get(&current->fs->root);
96
 
        read_unlock(&current->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);
100
 
        if (ns_root.mnt)
101
 
                ns_root.dentry = dget(ns_root.mnt->mnt_root);
102
 
        spin_unlock(&vfsmount_lock);
103
 
        spin_lock(&dcache_lock);
104
 
        tmp = ns_root;
105
 
        res = __d_path(path, &tmp, buf, buflen);
106
 
 
107
 
        *name = res;
108
 
        /* handle error conditions - and still allow a partial path to
109
 
         * be returned */
110
 
        if (IS_ERR(res)) {
111
 
                error = PTR_ERR(res);
112
 
                *name = buf;
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.
117
 
                 *
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
121
 
                 * strip it.
122
 
                 */
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)) {
129
 
                error = -ENOENT;
130
 
#if 0
131
 
        } else if (tmp.dentry != ns_root.dentry && tmp.mnt != ns_root.mnt) {
132
 
                /* disconnected path don return pathname starting with '/' */
133
 
                error = -ESTALE;
134
 
                if (*res == '/')
135
 
                        *name = res + 1;
136
 
#endif
137
 
        }
138
 
 
139
 
        spin_unlock(&dcache_lock);
140
 
        path_put(&root);
141
 
        path_put(&ns_root);
142
 
 
143
 
        return error;
144
 
}
145
 
 
146
 
char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
147
 
{
148
 
        if (buflen < 1)
149
 
                return NULL;
150
 
        buffer += --buflen;
151
 
        *buffer = '\0';
152
 
 
153
 
        while (table) {
154
 
                int namelen = strlen(table->procname);
155
 
 
156
 
                if (buflen < namelen + 1)
157
 
                        return NULL;
158
 
                buflen -= namelen + 1;
159
 
                buffer -= namelen;
160
 
                memcpy(buffer, table->procname, namelen);
161
 
                *--buffer = '/';
162
 
                table = table->parent;
163
 
        }
164
 
        if (buflen < 4)
165
 
                return NULL;
166
 
        buffer -= 4;
167
 
        memcpy(buffer, "/sys", 4);
168
 
 
169
 
        return buffer;
170
 
}