cregit-Linux how code gets into the kernel

Release 4.11 fs/overlayfs/inode.c

Directory: fs/overlayfs
/*
 *
 * Copyright (C) 2011 Novell Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */

#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/cred.h>
#include <linux/xattr.h>
#include <linux/posix_acl.h>
#include "overlayfs.h"


int ovl_setattr(struct dentry *dentry, struct iattr *attr) { int err; struct dentry *upperdentry; const struct cred *old_cred; /* * Check for permissions before trying to copy-up. This is redundant * since it will be rechecked later by ->setattr() on upper dentry. But * without this, copy-up can be triggered by just about anybody. * * We don't initialize inode->size, which just means that * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not * check for a swapfile (which this won't be anyway). */ err = setattr_prepare(dentry, attr); if (err) return err; err = ovl_want_write(dentry); if (err) goto out; err = ovl_copy_up(dentry); if (!err) { upperdentry = ovl_dentry_upper(dentry); if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) attr->ia_valid &= ~ATTR_MODE; inode_lock(upperdentry->d_inode); old_cred = ovl_override_creds(dentry->d_sb); err = notify_change(upperdentry, attr, NULL); revert_creds(old_cred); if (!err) ovl_copyattr(upperdentry->d_inode, dentry->d_inode); inode_unlock(upperdentry->d_inode); } ovl_drop_write(dentry); out: return err; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi12676.36%555.56%
Vivek Goyal2012.12%111.11%
Konstantin Khlebnikov169.70%111.11%
Al Viro21.21%111.11%
Jan Kara10.61%111.11%
Total165100.00%9100.00%


static int ovl_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) { struct dentry *dentry = path->dentry; struct path realpath; const struct cred *old_cred; int err; ovl_path_real(dentry, &realpath); old_cred = ovl_override_creds(dentry->d_sb); err = vfs_getattr(&realpath, stat, request_mask, flags); revert_creds(old_cred); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi3440.00%133.33%
Vivek Goyal2832.94%133.33%
David Howells2327.06%133.33%
Total85100.00%3100.00%


int ovl_permission(struct inode *inode, int mask) { bool is_upper; struct inode *realinode = ovl_inode_real(inode, &is_upper); const struct cred *old_cred; int err; /* Careful in RCU walk mode */ if (!realinode) { WARN_ON(!(mask & MAY_NOT_BLOCK)); return -ECHILD; } /* * Check overlay inode with the creds of task and underlying inode * with creds of mounter */ err = generic_permission(inode, mask); if (err) return err; old_cred = ovl_override_creds(inode->i_sb); if (!is_upper && !special_file(realinode->i_mode) && mask & MAY_WRITE) { mask &= ~(MAY_WRITE | MAY_APPEND); /* Make sure mounter can read file for copy up later */ mask |= MAY_READ; } err = inode_permission(realinode, mask); revert_creds(old_cred); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Vivek Goyal7454.41%444.44%
Miklos Szeredi5238.24%444.44%
Andreas Gruenbacher107.35%111.11%
Total136100.00%9100.00%


static const char *ovl_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { const struct cred *old_cred; const char *p; if (!dentry) return ERR_PTR(-ECHILD); old_cred = ovl_override_creds(dentry->d_sb); p = vfs_get_link(ovl_dentry_real(dentry), done); revert_creds(old_cred); return p; }

Contributors

PersonTokensPropCommitsCommitProp
Vivek Goyal3344.00%116.67%
Al Viro2533.33%350.00%
Miklos Szeredi1722.67%233.33%
Total75100.00%6100.00%


bool ovl_is_private_xattr(const char *name) { return strncmp(name, OVL_XATTR_PREFIX, sizeof(OVL_XATTR_PREFIX) - 1) == 0; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi2592.59%266.67%
Andreas Gruenbacher27.41%133.33%
Total27100.00%3100.00%


int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { int err; struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); const struct cred *old_cred; err = ovl_want_write(dentry); if (err) goto out; if (!value && !OVL_TYPE_UPPER(type)) { err = vfs_getxattr(realpath.dentry, name, NULL, 0); if (err < 0) goto out_drop_write; } err = ovl_copy_up(dentry); if (err) goto out_drop_write; if (!OVL_TYPE_UPPER(type)) ovl_path_upper(dentry, &realpath); old_cred = ovl_override_creds(dentry->d_sb); if (value) err = vfs_setxattr(realpath.dentry, name, value, size, flags); else { WARN_ON(flags != XATTR_REPLACE); err = vfs_removexattr(realpath.dentry, name); } revert_creds(old_cred); out_drop_write: ovl_drop_write(dentry); out: return err; }

Contributors

PersonTokensPropCommitsCommitProp
Andreas Gruenbacher9145.50%133.33%
Miklos Szeredi8944.50%133.33%
Vivek Goyal2010.00%133.33%
Total200100.00%3100.00%


int ovl_xattr_get(struct dentry *dentry, const char *name, void *value, size_t size) { struct dentry *realdentry = ovl_dentry_real(dentry); ssize_t res; const struct cred *old_cred; old_cred = ovl_override_creds(dentry->d_sb); res = vfs_getxattr(realdentry, name, value, size); revert_creds(old_cred); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi4157.75%360.00%
Vivek Goyal2839.44%120.00%
Andreas Gruenbacher22.82%120.00%
Total71100.00%5100.00%


ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { struct dentry *realdentry = ovl_dentry_real(dentry); ssize_t res; size_t len; char *s; const struct cred *old_cred; old_cred = ovl_override_creds(dentry->d_sb); res = vfs_listxattr(realdentry, list, size); revert_creds(old_cred); if (res <= 0 || size == 0) return res; /* filter out private xattrs */ for (s = list, len = res; len;) { size_t slen = strnlen(s, len) + 1; /* underlying fs providing us with an broken xattr list? */ if (WARN_ON(slen > len)) return -EIO; len -= slen; if (ovl_is_private_xattr(s)) { res -= slen; memmove(s, s + slen, len); } else { s += slen; } } return res; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi14187.58%480.00%
Vivek Goyal2012.42%120.00%
Total161100.00%5100.00%


struct posix_acl *ovl_get_acl(struct inode *inode, int type) { struct inode *realinode = ovl_inode_real(inode, NULL); const struct cred *old_cred; struct posix_acl *acl; if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) return NULL; old_cred = ovl_override_creds(inode->i_sb); acl = get_acl(realinode, type); revert_creds(old_cred); return acl; }

Contributors

PersonTokensPropCommitsCommitProp
Vivek Goyal7390.12%250.00%
Miklos Szeredi89.88%250.00%
Total81100.00%4100.00%


static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, struct dentry *realdentry) { if (OVL_TYPE_UPPER(type)) return false; if (special_file(realdentry->d_inode->i_mode)) return false; if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) return false; return true; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi67100.00%2100.00%
Total67100.00%2100.00%


int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags) { int err = 0; struct path realpath; enum ovl_path_type type; type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { err = ovl_want_write(dentry); if (!err) { err = ovl_copy_up_flags(dentry, file_flags); ovl_drop_write(dentry); } } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi7185.54%240.00%
David Howells910.84%240.00%
Amir Goldstein33.61%120.00%
Total83100.00%5100.00%


int ovl_update_time(struct inode *inode, struct timespec *ts, int flags) { struct dentry *alias; struct path upperpath; if (!(flags & S_ATIME)) return 0; alias = d_find_any_alias(inode); if (!alias) return 0; ovl_path_upper(alias, &upperpath); if (upperpath.dentry) { touch_atime(&upperpath); inode->i_atime = d_inode(upperpath.dentry)->i_atime; } dput(alias); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi97100.00%1100.00%
Total97100.00%1100.00%

static const struct inode_operations ovl_file_inode_operations = { .setattr = ovl_setattr, .permission = ovl_permission, .getattr = ovl_getattr, .listxattr = ovl_listxattr, .get_acl = ovl_get_acl, .update_time = ovl_update_time, }; static const struct inode_operations ovl_symlink_inode_operations = { .setattr = ovl_setattr, .get_link = ovl_get_link, .getattr = ovl_getattr, .listxattr = ovl_listxattr, .update_time = ovl_update_time, };
static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev) { inode->i_ino = get_next_ino(); inode->i_mode = mode; inode->i_flags |= S_NOCMTIME; #ifdef CONFIG_FS_POSIX_ACL inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE; #endif switch (mode & S_IFMT) { case S_IFREG: inode->i_op = &ovl_file_inode_operations; break; case S_IFDIR: inode->i_op = &ovl_dir_inode_operations; inode->i_fop = &ovl_dir_operations; break; case S_IFLNK: inode->i_op = &ovl_symlink_inode_operations; break; default: inode->i_op = &ovl_file_inode_operations; init_special_inode(inode, mode, rdev); break; } }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi117100.00%4100.00%
Total117100.00%4100.00%


struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev) { struct inode *inode; inode = new_inode(sb); if (inode) ovl_fill_inode(inode, mode, rdev); return inode; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi46100.00%3100.00%
Total46100.00%3100.00%


static int ovl_inode_test(struct inode *inode, void *data) { return ovl_inode_real(inode, NULL) == data; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi25100.00%2100.00%
Total25100.00%2100.00%


static int ovl_inode_set(struct inode *inode, void *data) { inode->i_private = (void *) (((unsigned long) data) | OVL_ISUPPER_MASK); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi38100.00%2100.00%
Total38100.00%2100.00%


struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode) { struct inode *inode; inode = iget5_locked(sb, (unsigned long) realinode, ovl_inode_test, ovl_inode_set, realinode); if (inode && inode->i_state & I_NEW) { ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); set_nlink(inode, realinode->i_nlink); unlock_new_inode(inode); } return inode; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi83100.00%3100.00%
Total83100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi115970.37%2048.78%
Vivek Goyal29918.15%614.63%
Andreas Gruenbacher1056.38%49.76%
David Howells321.94%37.32%
Al Viro291.76%49.76%
Konstantin Khlebnikov160.97%12.44%
Ingo Molnar30.18%12.44%
Amir Goldstein30.18%12.44%
Jan Kara10.06%12.44%
Total1647100.00%41100.00%
Directory: fs/overlayfs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.