~ubuntu-branches/ubuntu/raring/linux-nexus7/raring-proposed

« back to all changes in this revision

Viewing changes to fs/overlayfs/inode.c

  • Committer: Package Import Robot
  • Author(s): Tim Gardner, Andy Whitcroft, Erez Zadok, Miklos Szeredi, Neil Brown, Paolo Pisati, Tim Gardner
  • Date: 2013-02-27 11:55:02 UTC
  • Revision ID: package-import@ubuntu.com-20130227115502-979tupqdiwnd6bob
Tags: 3.1.10-10.28
[ Andy Whitcroft ]

* ubuntu: overlayfs -- overlayfs: add statfs support
  - LP: #1076317
* ubuntu: overlayfs -- overlayfs: apply device cgroup and security
  permissions to overlay files
  - LP: #1076317, #915941, #918212
  - CVE-2012-0055
* [packaging] Rename from linaro to nexus7 -- part 2

[ Erez Zadok ]

* ubuntu: overlayfs -- overlayfs: implement show_options
  - LP: #1076317

[ Miklos Szeredi ]

* ubuntu: overlayfs -- vfs: pass struct path to __dentry_open()
  - LP: #1076317
* ubuntu: overlayfs -- vfs: add i_op->open()
  - LP: #1076317
* ubuntu: overlayfs -- vfs: export do_splice_direct() to modules
  - LP: #1076317
* ubuntu: overlayfs -- vfs: introduce clone_private_mount()
  - LP: #1076317
* ubuntu: overlayfs -- overlay filesystem
  - LP: #1076317
* ubuntu: overlayfs -- fs: limit filesystem stacking depth
  - LP: #1076317

[ Neil Brown ]

* ubuntu: overlayfs -- overlay: overlay filesystem documentation
  - LP: #1076317

[ Paolo Pisati ]

* [Config] OVERLAYFS_FS=m
  - LP: #1076317
* SAUCE: compilation fix for missing symbols
  - LP: #1076317

[ Tim Gardner ]

* Rebased against git://phablet.ubuntu.com/CyanogenMod/android_kernel_asus_grouper.git phablet-10.1
* Updated configs to be more device consistent with
  arch/arm/configs/cyanogenmod_grouper_defconfig
  https://wiki.ubuntu.com/Touch/Porting#Kernel
  http://phablet.ubuntu.com/gitweb?p=CyanogenMod/android_kernel_asus_grouper.git;a=shortlog;h=refs/heads/phablet-10.1
* Pull config changes from git://phablet.ubuntu.com/CyanogenMod/android_kernel_asus_grouper.git phablet-10.1
  CONFIG_NAMESPACES=y
  CONFIG_UTS_NS=y
  CONFIG_IPC_NS=y
  CONFIG_USER_NS=y
  CONFIG_PID_NS=y
  CONFIG_NET_NS=y
  CONFIG_DEVTMPFS=y
  CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
  CONFIG_DNOTIFY=y
  CONFIG_FANOTIFY=y
  CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
  ONFIG_ANDROID_PARANOID_NETWORK=n
  ONFIG_DEVPTS_MULTIPLE_INSTANCES=y
  CONFIG_SYSVIPC=y
* [packaging] Rename from linaro to nexus7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (C) 2011 Novell Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 as published by
 
7
 * the Free Software Foundation.
 
8
 */
 
9
 
 
10
#include <linux/fs.h>
 
11
#include <linux/slab.h>
 
12
#include <linux/xattr.h>
 
13
#include <linux/device_cgroup.h>
 
14
#include <linux/security.h>
 
15
#include "overlayfs.h"
 
16
 
 
17
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
 
18
{
 
19
        struct dentry *upperdentry;
 
20
        int err;
 
21
 
 
22
        if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry))
 
23
                err = ovl_copy_up_truncate(dentry, attr->ia_size);
 
24
        else
 
25
                err = ovl_copy_up(dentry);
 
26
        if (err)
 
27
                return err;
 
28
 
 
29
        upperdentry = ovl_dentry_upper(dentry);
 
30
 
 
31
        if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
 
32
                attr->ia_valid &= ~ATTR_MODE;
 
33
 
 
34
        mutex_lock(&upperdentry->d_inode->i_mutex);
 
35
        err = notify_change(upperdentry, attr);
 
36
        mutex_unlock(&upperdentry->d_inode->i_mutex);
 
37
 
 
38
        return err;
 
39
}
 
40
 
 
41
static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
42
                         struct kstat *stat)
 
43
{
 
44
        struct path realpath;
 
45
 
 
46
        ovl_path_real(dentry, &realpath);
 
47
        return vfs_getattr(realpath.mnt, realpath.dentry, stat);
 
48
}
 
49
 
 
50
int ovl_permission(struct inode *inode, int mask)
 
51
{
 
52
        struct ovl_entry *oe;
 
53
        struct dentry *alias = NULL;
 
54
        struct inode *realinode;
 
55
        struct dentry *realdentry;
 
56
        bool is_upper;
 
57
        int err;
 
58
 
 
59
        if (S_ISDIR(inode->i_mode)) {
 
60
                oe = inode->i_private;
 
61
        } else if (mask & MAY_NOT_BLOCK) {
 
62
                return -ECHILD;
 
63
        } else {
 
64
                /*
 
65
                 * For non-directories find an alias and get the info
 
66
                 * from there.
 
67
                 */
 
68
                spin_lock(&inode->i_lock);
 
69
                if (WARN_ON(list_empty(&inode->i_dentry))) {
 
70
                        spin_unlock(&inode->i_lock);
 
71
                        return -ENOENT;
 
72
                }
 
73
                alias = list_entry(inode->i_dentry.next,
 
74
                                   struct dentry, d_alias);
 
75
                dget(alias);
 
76
                spin_unlock(&inode->i_lock);
 
77
                oe = alias->d_fsdata;
 
78
        }
 
79
 
 
80
        realdentry = ovl_entry_real(oe, &is_upper);
 
81
 
 
82
        /* Careful in RCU walk mode */
 
83
        realinode = ACCESS_ONCE(realdentry->d_inode);
 
84
        if (!realinode) {
 
85
                WARN_ON(!(mask & MAY_NOT_BLOCK));
 
86
                err = -ENOENT;
 
87
                goto out_dput;
 
88
        }
 
89
 
 
90
        if (mask & MAY_WRITE) {
 
91
                umode_t mode = realinode->i_mode;
 
92
 
 
93
                /*
 
94
                 * Writes will always be redirected to upper layer, so
 
95
                 * ignore lower layer being read-only.
 
96
                 *
 
97
                 * If the overlay itself is read-only then proceed
 
98
                 * with the permission check, don't return EROFS.
 
99
                 * This will only happen if this is the lower layer of
 
100
                 * another overlayfs.
 
101
                 *
 
102
                 * If upper fs becomes read-only after the overlay was
 
103
                 * constructed return EROFS to prevent modification of
 
104
                 * upper layer.
 
105
                 */
 
106
                err = -EROFS;
 
107
                if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
 
108
                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
 
109
                        goto out_dput;
 
110
 
 
111
                /*
 
112
                 * Nobody gets write access to an immutable file.
 
113
                 */
 
114
                err = -EACCES;
 
115
                if (IS_IMMUTABLE(realinode))
 
116
                        goto out_dput;
 
117
        }
 
118
 
 
119
        if (realinode->i_op->permission)
 
120
                err = realinode->i_op->permission(realinode, mask);
 
121
        else
 
122
                err = generic_permission(realinode, mask);
 
123
 
 
124
        if (!err)
 
125
                err = devcgroup_inode_permission(realinode, mask);
 
126
        if (!err)
 
127
                err = security_inode_permission(realinode, mask);
 
128
out_dput:
 
129
        dput(alias);
 
130
        return err;
 
131
}
 
132
 
 
133
 
 
134
struct ovl_link_data {
 
135
        struct dentry *realdentry;
 
136
        void *cookie;
 
137
};
 
138
 
 
139
static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
 
140
{
 
141
        void *ret;
 
142
        struct dentry *realdentry;
 
143
        struct inode *realinode;
 
144
 
 
145
        realdentry = ovl_dentry_real(dentry);
 
146
        realinode = realdentry->d_inode;
 
147
 
 
148
        if (WARN_ON(!realinode->i_op->follow_link))
 
149
                return ERR_PTR(-EPERM);
 
150
 
 
151
        ret = realinode->i_op->follow_link(realdentry, nd);
 
152
        if (IS_ERR(ret))
 
153
                return ret;
 
154
 
 
155
        if (realinode->i_op->put_link) {
 
156
                struct ovl_link_data *data;
 
157
 
 
158
                data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
 
159
                if (!data) {
 
160
                        realinode->i_op->put_link(realdentry, nd, ret);
 
161
                        return ERR_PTR(-ENOMEM);
 
162
                }
 
163
                data->realdentry = realdentry;
 
164
                data->cookie = ret;
 
165
 
 
166
                return data;
 
167
        } else {
 
168
                return NULL;
 
169
        }
 
170
}
 
171
 
 
172
static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
 
173
{
 
174
        struct inode *realinode;
 
175
        struct ovl_link_data *data = c;
 
176
 
 
177
        if (!data)
 
178
                return;
 
179
 
 
180
        realinode = data->realdentry->d_inode;
 
181
        realinode->i_op->put_link(data->realdentry, nd, data->cookie);
 
182
        kfree(data);
 
183
}
 
184
 
 
185
static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
 
186
{
 
187
        struct path realpath;
 
188
        struct inode *realinode;
 
189
 
 
190
        ovl_path_real(dentry, &realpath);
 
191
        realinode = realpath.dentry->d_inode;
 
192
 
 
193
        if (!realinode->i_op->readlink)
 
194
                return -EINVAL;
 
195
 
 
196
        touch_atime(realpath.mnt, realpath.dentry);
 
197
 
 
198
        return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
 
199
}
 
200
 
 
201
 
 
202
static bool ovl_is_private_xattr(const char *name)
 
203
{
 
204
        return strncmp(name, "trusted.overlay.", 14) == 0;
 
205
}
 
206
 
 
207
int ovl_setxattr(struct dentry *dentry, const char *name,
 
208
                 const void *value, size_t size, int flags)
 
209
{
 
210
        int err;
 
211
        struct dentry *upperdentry;
 
212
 
 
213
        if (ovl_is_private_xattr(name))
 
214
                return -EPERM;
 
215
 
 
216
        err = ovl_copy_up(dentry);
 
217
        if (err)
 
218
                return err;
 
219
 
 
220
        upperdentry = ovl_dentry_upper(dentry);
 
221
        return  vfs_setxattr(upperdentry, name, value, size, flags);
 
222
}
 
223
 
 
224
ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
 
225
                     void *value, size_t size)
 
226
{
 
227
        if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
 
228
            ovl_is_private_xattr(name))
 
229
                return -ENODATA;
 
230
 
 
231
        return vfs_getxattr(ovl_dentry_real(dentry), name, value, size);
 
232
}
 
233
 
 
234
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
 
235
{
 
236
        ssize_t res;
 
237
        int off;
 
238
 
 
239
        res = vfs_listxattr(ovl_dentry_real(dentry), list, size);
 
240
        if (res <= 0 || size == 0)
 
241
                return res;
 
242
 
 
243
        if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE)
 
244
                return res;
 
245
 
 
246
        /* filter out private xattrs */
 
247
        for (off = 0; off < res;) {
 
248
                char *s = list + off;
 
249
                size_t slen = strlen(s) + 1;
 
250
 
 
251
                BUG_ON(off + slen > res);
 
252
 
 
253
                if (ovl_is_private_xattr(s)) {
 
254
                        res -= slen;
 
255
                        memmove(s, s + slen, res - off);
 
256
                } else {
 
257
                        off += slen;
 
258
                }
 
259
        }
 
260
 
 
261
        return res;
 
262
}
 
263
 
 
264
int ovl_removexattr(struct dentry *dentry, const char *name)
 
265
{
 
266
        int err;
 
267
        struct path realpath;
 
268
        enum ovl_path_type type;
 
269
 
 
270
        if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
 
271
            ovl_is_private_xattr(name))
 
272
                return -ENODATA;
 
273
 
 
274
        type = ovl_path_real(dentry, &realpath);
 
275
        if (type == OVL_PATH_LOWER) {
 
276
                err = vfs_getxattr(realpath.dentry, name, NULL, 0);
 
277
                if (err < 0)
 
278
                        return err;
 
279
 
 
280
                err = ovl_copy_up(dentry);
 
281
                if (err)
 
282
                        return err;
 
283
 
 
284
                ovl_path_upper(dentry, &realpath);
 
285
        }
 
286
 
 
287
        return vfs_removexattr(realpath.dentry, name);
 
288
}
 
289
 
 
290
static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
 
291
                                  struct dentry *realdentry)
 
292
{
 
293
        if (type != OVL_PATH_LOWER)
 
294
                return false;
 
295
 
 
296
        if (special_file(realdentry->d_inode->i_mode))
 
297
                return false;
 
298
 
 
299
        if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
 
300
                return false;
 
301
 
 
302
        return true;
 
303
}
 
304
 
 
305
static struct file *ovl_open(struct dentry *dentry, struct file *file,
 
306
                             const struct cred *cred)
 
307
{
 
308
        int err;
 
309
        struct path realpath;
 
310
        enum ovl_path_type type;
 
311
 
 
312
        type = ovl_path_real(dentry, &realpath);
 
313
        if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) {
 
314
                if (file->f_flags & O_TRUNC)
 
315
                        err = ovl_copy_up_truncate(dentry, 0);
 
316
                else
 
317
                        err = ovl_copy_up(dentry);
 
318
                if (err)
 
319
                        return ERR_PTR(err);
 
320
 
 
321
                ovl_path_upper(dentry, &realpath);
 
322
        }
 
323
 
 
324
        return vfs_open(&realpath, file, cred);
 
325
}
 
326
 
 
327
static const struct inode_operations ovl_file_inode_operations = {
 
328
        .setattr        = ovl_setattr,
 
329
        .permission     = ovl_permission,
 
330
        .getattr        = ovl_getattr,
 
331
        .setxattr       = ovl_setxattr,
 
332
        .getxattr       = ovl_getxattr,
 
333
        .listxattr      = ovl_listxattr,
 
334
        .removexattr    = ovl_removexattr,
 
335
        .open           = ovl_open,
 
336
};
 
337
 
 
338
static const struct inode_operations ovl_symlink_inode_operations = {
 
339
        .setattr        = ovl_setattr,
 
340
        .follow_link    = ovl_follow_link,
 
341
        .put_link       = ovl_put_link,
 
342
        .readlink       = ovl_readlink,
 
343
        .getattr        = ovl_getattr,
 
344
        .setxattr       = ovl_setxattr,
 
345
        .getxattr       = ovl_getxattr,
 
346
        .listxattr      = ovl_listxattr,
 
347
        .removexattr    = ovl_removexattr,
 
348
};
 
349
 
 
350
struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
 
351
                            struct ovl_entry *oe)
 
352
{
 
353
        struct inode *inode;
 
354
 
 
355
        inode = new_inode(sb);
 
356
        if (!inode)
 
357
                return NULL;
 
358
 
 
359
        mode &= S_IFMT;
 
360
 
 
361
        inode->i_ino = get_next_ino();
 
362
        inode->i_mode = mode;
 
363
        inode->i_flags |= S_NOATIME | S_NOCMTIME;
 
364
 
 
365
        switch (mode) {
 
366
        case S_IFDIR:
 
367
                inode->i_private = oe;
 
368
                inode->i_op = &ovl_dir_inode_operations;
 
369
                inode->i_fop = &ovl_dir_operations;
 
370
                break;
 
371
 
 
372
        case S_IFLNK:
 
373
                inode->i_op = &ovl_symlink_inode_operations;
 
374
                break;
 
375
 
 
376
        case S_IFREG:
 
377
        case S_IFSOCK:
 
378
        case S_IFBLK:
 
379
        case S_IFCHR:
 
380
        case S_IFIFO:
 
381
                inode->i_op = &ovl_file_inode_operations;
 
382
                break;
 
383
 
 
384
        default:
 
385
                WARN(1, "illegal file type: %i\n", mode);
 
386
                inode = NULL;
 
387
        }
 
388
 
 
389
        return inode;
 
390
 
 
391
}