~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise-security

« back to all changes in this revision

Viewing changes to fs/xfs/linux-2.6/xfs_xattr.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-12-06 15:56:07 UTC
  • Revision ID: package-import@ubuntu.com-20111206155607-pcf44kv5fmhk564f
Tags: 3.2.0-1401.1
[ Paolo Pisati ]

* Rebased on top of Ubuntu-3.2.0-3.8
* Tilt-tracking @ ef2487af4bb15bdd0689631774b5a5e3a59f74e2
* Delete debian.ti-omap4/control, it shoudln't be tracked
* Fix architecture spelling (s/armel/armhf/)
* [Config] Update configs following 3.2 import
* [Config] Fix compilation: disable CODA and ARCH_OMAP3
* [Config] Fix compilation: disable Ethernet Faraday
* Update series to precise

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2008 Christoph Hellwig.
3
 
 * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU General Public License as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * This program is distributed in the hope that it would be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write the Free Software Foundation,
16
 
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
 
 */
18
 
 
19
 
#include "xfs.h"
20
 
#include "xfs_da_btree.h"
21
 
#include "xfs_bmap_btree.h"
22
 
#include "xfs_inode.h"
23
 
#include "xfs_attr.h"
24
 
#include "xfs_attr_leaf.h"
25
 
#include "xfs_acl.h"
26
 
#include "xfs_vnodeops.h"
27
 
 
28
 
#include <linux/posix_acl_xattr.h>
29
 
#include <linux/xattr.h>
30
 
 
31
 
 
32
 
static int
33
 
xfs_xattr_get(struct dentry *dentry, const char *name,
34
 
                void *value, size_t size, int xflags)
35
 
{
36
 
        struct xfs_inode *ip = XFS_I(dentry->d_inode);
37
 
        int error, asize = size;
38
 
 
39
 
        if (strcmp(name, "") == 0)
40
 
                return -EINVAL;
41
 
 
42
 
        /* Convert Linux syscall to XFS internal ATTR flags */
43
 
        if (!size) {
44
 
                xflags |= ATTR_KERNOVAL;
45
 
                value = NULL;
46
 
        }
47
 
 
48
 
        error = -xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
49
 
        if (error)
50
 
                return error;
51
 
        return asize;
52
 
}
53
 
 
54
 
static int
55
 
xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
56
 
                size_t size, int flags, int xflags)
57
 
{
58
 
        struct xfs_inode *ip = XFS_I(dentry->d_inode);
59
 
 
60
 
        if (strcmp(name, "") == 0)
61
 
                return -EINVAL;
62
 
 
63
 
        /* Convert Linux syscall to XFS internal ATTR flags */
64
 
        if (flags & XATTR_CREATE)
65
 
                xflags |= ATTR_CREATE;
66
 
        if (flags & XATTR_REPLACE)
67
 
                xflags |= ATTR_REPLACE;
68
 
 
69
 
        if (!value)
70
 
                return -xfs_attr_remove(ip, (unsigned char *)name, xflags);
71
 
        return -xfs_attr_set(ip, (unsigned char *)name,
72
 
                                (void *)value, size, xflags);
73
 
}
74
 
 
75
 
static const struct xattr_handler xfs_xattr_user_handler = {
76
 
        .prefix = XATTR_USER_PREFIX,
77
 
        .flags  = 0, /* no flags implies user namespace */
78
 
        .get    = xfs_xattr_get,
79
 
        .set    = xfs_xattr_set,
80
 
};
81
 
 
82
 
static const struct xattr_handler xfs_xattr_trusted_handler = {
83
 
        .prefix = XATTR_TRUSTED_PREFIX,
84
 
        .flags  = ATTR_ROOT,
85
 
        .get    = xfs_xattr_get,
86
 
        .set    = xfs_xattr_set,
87
 
};
88
 
 
89
 
static const struct xattr_handler xfs_xattr_security_handler = {
90
 
        .prefix = XATTR_SECURITY_PREFIX,
91
 
        .flags  = ATTR_SECURE,
92
 
        .get    = xfs_xattr_get,
93
 
        .set    = xfs_xattr_set,
94
 
};
95
 
 
96
 
const struct xattr_handler *xfs_xattr_handlers[] = {
97
 
        &xfs_xattr_user_handler,
98
 
        &xfs_xattr_trusted_handler,
99
 
        &xfs_xattr_security_handler,
100
 
#ifdef CONFIG_XFS_POSIX_ACL
101
 
        &xfs_xattr_acl_access_handler,
102
 
        &xfs_xattr_acl_default_handler,
103
 
#endif
104
 
        NULL
105
 
};
106
 
 
107
 
static unsigned int xfs_xattr_prefix_len(int flags)
108
 
{
109
 
        if (flags & XFS_ATTR_SECURE)
110
 
                return sizeof("security");
111
 
        else if (flags & XFS_ATTR_ROOT)
112
 
                return sizeof("trusted");
113
 
        else
114
 
                return sizeof("user");
115
 
}
116
 
 
117
 
static const char *xfs_xattr_prefix(int flags)
118
 
{
119
 
        if (flags & XFS_ATTR_SECURE)
120
 
                return xfs_xattr_security_handler.prefix;
121
 
        else if (flags & XFS_ATTR_ROOT)
122
 
                return xfs_xattr_trusted_handler.prefix;
123
 
        else
124
 
                return xfs_xattr_user_handler.prefix;
125
 
}
126
 
 
127
 
static int
128
 
xfs_xattr_put_listent(
129
 
        struct xfs_attr_list_context *context,
130
 
        int             flags,
131
 
        unsigned char   *name,
132
 
        int             namelen,
133
 
        int             valuelen,
134
 
        unsigned char   *value)
135
 
{
136
 
        unsigned int prefix_len = xfs_xattr_prefix_len(flags);
137
 
        char *offset;
138
 
        int arraytop;
139
 
 
140
 
        ASSERT(context->count >= 0);
141
 
 
142
 
        /*
143
 
         * Only show root namespace entries if we are actually allowed to
144
 
         * see them.
145
 
         */
146
 
        if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
147
 
                return 0;
148
 
 
149
 
        arraytop = context->count + prefix_len + namelen + 1;
150
 
        if (arraytop > context->firstu) {
151
 
                context->count = -1;    /* insufficient space */
152
 
                return 1;
153
 
        }
154
 
        offset = (char *)context->alist + context->count;
155
 
        strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
156
 
        offset += prefix_len;
157
 
        strncpy(offset, (char *)name, namelen);                 /* real name */
158
 
        offset += namelen;
159
 
        *offset = '\0';
160
 
        context->count += prefix_len + namelen + 1;
161
 
        return 0;
162
 
}
163
 
 
164
 
static int
165
 
xfs_xattr_put_listent_sizes(
166
 
        struct xfs_attr_list_context *context,
167
 
        int             flags,
168
 
        unsigned char   *name,
169
 
        int             namelen,
170
 
        int             valuelen,
171
 
        unsigned char   *value)
172
 
{
173
 
        context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
174
 
        return 0;
175
 
}
176
 
 
177
 
static int
178
 
list_one_attr(const char *name, const size_t len, void *data,
179
 
                size_t size, ssize_t *result)
180
 
{
181
 
        char *p = data + *result;
182
 
 
183
 
        *result += len;
184
 
        if (!size)
185
 
                return 0;
186
 
        if (*result > size)
187
 
                return -ERANGE;
188
 
 
189
 
        strcpy(p, name);
190
 
        return 0;
191
 
}
192
 
 
193
 
ssize_t
194
 
xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
195
 
{
196
 
        struct xfs_attr_list_context context;
197
 
        struct attrlist_cursor_kern cursor = { 0 };
198
 
        struct inode            *inode = dentry->d_inode;
199
 
        int                     error;
200
 
 
201
 
        /*
202
 
         * First read the regular on-disk attributes.
203
 
         */
204
 
        memset(&context, 0, sizeof(context));
205
 
        context.dp = XFS_I(inode);
206
 
        context.cursor = &cursor;
207
 
        context.resynch = 1;
208
 
        context.alist = data;
209
 
        context.bufsize = size;
210
 
        context.firstu = context.bufsize;
211
 
 
212
 
        if (size)
213
 
                context.put_listent = xfs_xattr_put_listent;
214
 
        else
215
 
                context.put_listent = xfs_xattr_put_listent_sizes;
216
 
 
217
 
        xfs_attr_list_int(&context);
218
 
        if (context.count < 0)
219
 
                return -ERANGE;
220
 
 
221
 
        /*
222
 
         * Then add the two synthetic ACL attributes.
223
 
         */
224
 
        if (posix_acl_access_exists(inode)) {
225
 
                error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
226
 
                                strlen(POSIX_ACL_XATTR_ACCESS) + 1,
227
 
                                data, size, &context.count);
228
 
                if (error)
229
 
                        return error;
230
 
        }
231
 
 
232
 
        if (posix_acl_default_exists(inode)) {
233
 
                error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
234
 
                                strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
235
 
                                data, size, &context.count);
236
 
                if (error)
237
 
                        return error;
238
 
        }
239
 
 
240
 
        return context.count;
241
 
}