Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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 "overlayfs.h"
 14
 15static int ovl_copy_up_truncate(struct dentry *dentry)
 16{
 17	int err;
 18	struct dentry *parent;
 19	struct kstat stat;
 20	struct path lowerpath;
 21
 22	parent = dget_parent(dentry);
 23	err = ovl_copy_up(parent);
 24	if (err)
 25		goto out_dput_parent;
 26
 27	ovl_path_lower(dentry, &lowerpath);
 28	err = vfs_getattr(&lowerpath, &stat);
 29	if (err)
 30		goto out_dput_parent;
 31
 32	stat.size = 0;
 33	err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat);
 34
 35out_dput_parent:
 36	dput(parent);
 37	return err;
 38}
 39
 40int ovl_setattr(struct dentry *dentry, struct iattr *attr)
 41{
 42	int err;
 43	struct dentry *upperdentry;
 44
 45	/*
 46	 * Check for permissions before trying to copy-up.  This is redundant
 47	 * since it will be rechecked later by ->setattr() on upper dentry.  But
 48	 * without this, copy-up can be triggered by just about anybody.
 49	 *
 50	 * We don't initialize inode->size, which just means that
 51	 * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
 52	 * check for a swapfile (which this won't be anyway).
 53	 */
 54	err = inode_change_ok(dentry->d_inode, attr);
 55	if (err)
 56		return err;
 57
 58	err = ovl_want_write(dentry);
 59	if (err)
 60		goto out;
 61
 62	err = ovl_copy_up(dentry);
 63	if (!err) {
 64		upperdentry = ovl_dentry_upper(dentry);
 65
 66		inode_lock(upperdentry->d_inode);
 67		err = notify_change(upperdentry, attr, NULL);
 68		if (!err)
 69			ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
 70		inode_unlock(upperdentry->d_inode);
 71	}
 72	ovl_drop_write(dentry);
 73out:
 74	return err;
 75}
 76
 77static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
 78			 struct kstat *stat)
 79{
 80	struct path realpath;
 81
 82	ovl_path_real(dentry, &realpath);
 83	return vfs_getattr(&realpath, stat);
 84}
 85
 86int ovl_permission(struct inode *inode, int mask)
 87{
 88	struct ovl_entry *oe;
 89	struct dentry *alias = NULL;
 90	struct inode *realinode;
 91	struct dentry *realdentry;
 92	bool is_upper;
 93	int err;
 94
 95	if (S_ISDIR(inode->i_mode)) {
 96		oe = inode->i_private;
 97	} else if (mask & MAY_NOT_BLOCK) {
 98		return -ECHILD;
 99	} else {
100		/*
101		 * For non-directories find an alias and get the info
102		 * from there.
103		 */
104		alias = d_find_any_alias(inode);
105		if (WARN_ON(!alias))
106			return -ENOENT;
107
108		oe = alias->d_fsdata;
109	}
110
111	realdentry = ovl_entry_real(oe, &is_upper);
112
113	if (ovl_is_default_permissions(inode)) {
114		struct kstat stat;
115		struct path realpath = { .dentry = realdentry };
116
117		if (mask & MAY_NOT_BLOCK)
118			return -ECHILD;
119
120		realpath.mnt = ovl_entry_mnt_real(oe, inode, is_upper);
121
122		err = vfs_getattr(&realpath, &stat);
123		if (err)
124			return err;
125
126		if ((stat.mode ^ inode->i_mode) & S_IFMT)
127			return -ESTALE;
128
129		inode->i_mode = stat.mode;
130		inode->i_uid = stat.uid;
131		inode->i_gid = stat.gid;
132
133		return generic_permission(inode, mask);
134	}
135
136	/* Careful in RCU walk mode */
137	realinode = ACCESS_ONCE(realdentry->d_inode);
138	if (!realinode) {
139		WARN_ON(!(mask & MAY_NOT_BLOCK));
140		err = -ENOENT;
141		goto out_dput;
142	}
143
144	if (mask & MAY_WRITE) {
145		umode_t mode = realinode->i_mode;
146
147		/*
148		 * Writes will always be redirected to upper layer, so
149		 * ignore lower layer being read-only.
150		 *
151		 * If the overlay itself is read-only then proceed
152		 * with the permission check, don't return EROFS.
153		 * This will only happen if this is the lower layer of
154		 * another overlayfs.
155		 *
156		 * If upper fs becomes read-only after the overlay was
157		 * constructed return EROFS to prevent modification of
158		 * upper layer.
159		 */
160		err = -EROFS;
161		if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
162		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
163			goto out_dput;
164	}
165
166	err = __inode_permission(realinode, mask);
167out_dput:
168	dput(alias);
169	return err;
170}
171
172static const char *ovl_get_link(struct dentry *dentry,
173				struct inode *inode,
174				struct delayed_call *done)
175{
176	struct dentry *realdentry;
177	struct inode *realinode;
178
179	if (!dentry)
180		return ERR_PTR(-ECHILD);
181
182	realdentry = ovl_dentry_real(dentry);
183	realinode = realdentry->d_inode;
184
185	if (WARN_ON(!realinode->i_op->get_link))
186		return ERR_PTR(-EPERM);
187
188	return realinode->i_op->get_link(realdentry, realinode, done);
189}
190
191static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
192{
193	struct path realpath;
194	struct inode *realinode;
195
196	ovl_path_real(dentry, &realpath);
197	realinode = realpath.dentry->d_inode;
198
199	if (!realinode->i_op->readlink)
200		return -EINVAL;
201
202	touch_atime(&realpath);
203
204	return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
205}
206
207
208static bool ovl_is_private_xattr(const char *name)
209{
210	return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
211}
212
213int ovl_setxattr(struct dentry *dentry, const char *name,
214		 const void *value, size_t size, int flags)
215{
216	int err;
217	struct dentry *upperdentry;
218
219	err = ovl_want_write(dentry);
220	if (err)
221		goto out;
222
223	err = -EPERM;
224	if (ovl_is_private_xattr(name))
225		goto out_drop_write;
226
227	err = ovl_copy_up(dentry);
228	if (err)
229		goto out_drop_write;
230
231	upperdentry = ovl_dentry_upper(dentry);
232	err = vfs_setxattr(upperdentry, name, value, size, flags);
233
234out_drop_write:
235	ovl_drop_write(dentry);
236out:
237	return err;
238}
239
240static bool ovl_need_xattr_filter(struct dentry *dentry,
241				  enum ovl_path_type type)
242{
243	if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
244		return S_ISDIR(dentry->d_inode->i_mode);
245	else
246		return false;
247}
248
249ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
250		     void *value, size_t size)
251{
252	struct path realpath;
253	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
254
255	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
256		return -ENODATA;
257
258	return vfs_getxattr(realpath.dentry, name, value, size);
259}
260
261ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
262{
263	struct path realpath;
264	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
265	ssize_t res;
266	int off;
267
268	res = vfs_listxattr(realpath.dentry, list, size);
269	if (res <= 0 || size == 0)
270		return res;
271
272	if (!ovl_need_xattr_filter(dentry, type))
273		return res;
274
275	/* filter out private xattrs */
276	for (off = 0; off < res;) {
277		char *s = list + off;
278		size_t slen = strlen(s) + 1;
279
280		BUG_ON(off + slen > res);
281
282		if (ovl_is_private_xattr(s)) {
283			res -= slen;
284			memmove(s, s + slen, res - off);
285		} else {
286			off += slen;
287		}
288	}
289
290	return res;
291}
292
293int ovl_removexattr(struct dentry *dentry, const char *name)
294{
295	int err;
296	struct path realpath;
297	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
298
299	err = ovl_want_write(dentry);
300	if (err)
301		goto out;
302
303	err = -ENODATA;
304	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
305		goto out_drop_write;
306
307	if (!OVL_TYPE_UPPER(type)) {
308		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
309		if (err < 0)
310			goto out_drop_write;
311
312		err = ovl_copy_up(dentry);
313		if (err)
314			goto out_drop_write;
315
316		ovl_path_upper(dentry, &realpath);
317	}
318
319	err = vfs_removexattr(realpath.dentry, name);
320out_drop_write:
321	ovl_drop_write(dentry);
322out:
323	return err;
324}
325
326static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
327				  struct dentry *realdentry)
328{
329	if (OVL_TYPE_UPPER(type))
330		return false;
331
332	if (special_file(realdentry->d_inode->i_mode))
333		return false;
334
335	if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
336		return false;
337
338	return true;
339}
340
341struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags)
342{
343	int err;
344	struct path realpath;
345	enum ovl_path_type type;
346
347	if (d_is_dir(dentry))
348		return d_backing_inode(dentry);
349
350	type = ovl_path_real(dentry, &realpath);
351	if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
352		err = ovl_want_write(dentry);
353		if (err)
354			return ERR_PTR(err);
355
356		if (file_flags & O_TRUNC)
357			err = ovl_copy_up_truncate(dentry);
358		else
359			err = ovl_copy_up(dentry);
360		ovl_drop_write(dentry);
361		if (err)
362			return ERR_PTR(err);
363
364		ovl_path_upper(dentry, &realpath);
365	}
366
367	if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
368		return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
369
370	return d_backing_inode(realpath.dentry);
371}
372
373static const struct inode_operations ovl_file_inode_operations = {
374	.setattr	= ovl_setattr,
375	.permission	= ovl_permission,
376	.getattr	= ovl_getattr,
377	.setxattr	= ovl_setxattr,
378	.getxattr	= ovl_getxattr,
379	.listxattr	= ovl_listxattr,
380	.removexattr	= ovl_removexattr,
381};
382
383static const struct inode_operations ovl_symlink_inode_operations = {
384	.setattr	= ovl_setattr,
385	.get_link	= ovl_get_link,
386	.readlink	= ovl_readlink,
387	.getattr	= ovl_getattr,
388	.setxattr	= ovl_setxattr,
389	.getxattr	= ovl_getxattr,
390	.listxattr	= ovl_listxattr,
391	.removexattr	= ovl_removexattr,
392};
393
394struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
395			    struct ovl_entry *oe)
396{
397	struct inode *inode;
398
399	inode = new_inode(sb);
400	if (!inode)
401		return NULL;
402
403	mode &= S_IFMT;
404
405	inode->i_ino = get_next_ino();
406	inode->i_mode = mode;
407	inode->i_flags |= S_NOATIME | S_NOCMTIME;
408
409	switch (mode) {
410	case S_IFDIR:
411		inode->i_private = oe;
412		inode->i_op = &ovl_dir_inode_operations;
413		inode->i_fop = &ovl_dir_operations;
414		break;
415
416	case S_IFLNK:
417		inode->i_op = &ovl_symlink_inode_operations;
418		break;
419
420	case S_IFREG:
421	case S_IFSOCK:
422	case S_IFBLK:
423	case S_IFCHR:
424	case S_IFIFO:
425		inode->i_op = &ovl_file_inode_operations;
426		break;
427
428	default:
429		WARN(1, "illegal file type: %i\n", mode);
430		iput(inode);
431		inode = NULL;
432	}
433
434	return inode;
435}