Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (38 commits)
  direct I/O fallback sync simplification
  ocfs: stop using do_sync_mapping_range
  cleanup blockdev_direct_IO locking
  make generic_acl slightly more generic
  sanitize xattr handler prototypes
  libfs: move EXPORT_SYMBOL for d_alloc_name
  vfs: force reval of target when following LAST_BIND symlinks (try #7)
  ima: limit imbalance msg
  Untangling ima mess, part 3: kill dead code in ima
  Untangling ima mess, part 2: deal with counters
  Untangling ima mess, part 1: alloc_file()
  O_TRUNC open shouldn't fail after file truncation
  ima: call ima_inode_free ima_inode_free
  IMA: clean up the IMA counts updating code
  ima: only insert at inode creation time
  ima: valid return code from ima_inode_alloc
  fs: move get_empty_filp() deffinition to internal.h
  Sanitize exec_permission_lite()
  Kill cached_lookup() and real_lookup()
  Kill path_lookup_open()
  ...

Trivial conflicts in fs/direct-io.c
This commit is contained in:
Linus Torvalds 2009-12-16 12:04:02 -08:00
commit bac5e54c29
81 changed files with 1173 additions and 1832 deletions

View file

@ -2200,7 +2200,7 @@ pfm_alloc_file(pfm_context_t *ctx)
{
struct file *file;
struct inode *inode;
struct dentry *dentry;
struct path path;
char name[32];
struct qstr this;
@ -2225,18 +2225,19 @@ pfm_alloc_file(pfm_context_t *ctx)
/*
* allocate a new dcache entry
*/
dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
if (!dentry) {
path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
if (!path.dentry) {
iput(inode);
return ERR_PTR(-ENOMEM);
}
path.mnt = mntget(pfmfs_mnt);
dentry->d_op = &pfmfs_dentry_operations;
d_add(dentry, inode);
path.dentry->d_op = &pfmfs_dentry_operations;
d_add(path.dentry, inode);
file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops);
file = alloc_file(&path, FMODE_READ, &pfm_file_ops);
if (!file) {
dput(dentry);
path_put(&path);
return ERR_PTR(-ENFILE);
}

View file

@ -445,12 +445,7 @@ done:
int hpux_pipe(int *kstack_fildes)
{
int error;
lock_kernel();
error = do_pipe_flags(kstack_fildes, 0);
unlock_kernel();
return error;
return do_pipe_flags(kstack_fildes, 0);
}
/* lies - says it works, but it really didn't lock anything */

View file

@ -30,7 +30,6 @@ struct mmap_arg_struct;
asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
asmlinkage long sys32_pipe(int __user *);
struct sigaction32;
struct old_sigaction32;
asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,

View file

@ -12,7 +12,6 @@ struct pt_regs;
struct sigaction;
asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
asmlinkage long xtensa_pipe(int __user *);
asmlinkage long xtensa_ptrace(long, long, long, long);
asmlinkage long xtensa_sigreturn(struct pt_regs*);
asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);

View file

@ -94,7 +94,7 @@ __SYSCALL( 35, sys_readlink, 3)
#define __NR_mknod 36
__SYSCALL( 36, sys_mknod, 3)
#define __NR_pipe 37
__SYSCALL( 37, xtensa_pipe, 1)
__SYSCALL( 37, sys_pipe, 1)
#define __NR_unlink 38
__SYSCALL( 38, sys_unlink, 1)
#define __NR_rmdir 39

View file

@ -39,24 +39,6 @@ syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
#include <asm/unistd.h>
};
/*
* xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
* the way unix traditional does this, though.
*/
asmlinkage long xtensa_pipe(int __user *userfds)
{
int fd[2];
int error;
error = do_pipe_flags(fd, 0);
if (!error) {
if (copy_to_user(userfds, fd, 2 * sizeof(int)))
error = -EFAULT;
}
return error;
}
asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
{
unsigned long ret;

View file

@ -492,6 +492,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
int is_async, int *fd)
{
struct ib_uverbs_event_file *ev_file;
struct path path;
struct file *filp;
int ret;
@ -519,8 +520,10 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
* system call on a uverbs file, which will already have a
* module reference.
*/
filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root),
FMODE_READ, fops_get(&uverbs_event_fops));
path.mnt = uverbs_event_mnt;
path.dentry = uverbs_event_mnt->mnt_root;
path_get(&path);
filp = alloc_file(&path, FMODE_READ, fops_get(&uverbs_event_fops));
if (!filp) {
ret = -ENFILE;
goto err_fd;
@ -531,6 +534,8 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
return filp;
err_fd:
fops_put(&uverbs_event_fops);
path_put(&path);
put_unused_fd(*fd);
err:

View file

@ -403,7 +403,7 @@ static void dst_node_cleanup(struct dst_node *n)
if (n->bdev) {
sync_blockdev(n->bdev);
blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
}
dst_state_lock(st);
@ -463,37 +463,6 @@ void dst_node_put(struct dst_node *n)
}
}
/*
* This function finds devices major/minor numbers for given pathname.
*/
static int dst_lookup_device(const char *path, dev_t *dev)
{
int err;
struct nameidata nd;
struct inode *inode;
err = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (err)
return err;
inode = nd.path.dentry->d_inode;
if (!inode) {
err = -ENOENT;
goto out;
}
if (!S_ISBLK(inode->i_mode)) {
err = -ENOTBLK;
goto out;
}
*dev = inode->i_rdev;
out:
path_put(&nd.path);
return err;
}
/*
* Setting up export device: lookup by the name, get its size
* and setup listening socket, which will accept clients, which
@ -503,17 +472,12 @@ static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
struct dst_export_ctl *le)
{
int err;
dev_t dev = 0; /* gcc likes to scream here */
snprintf(n->info->local, sizeof(n->info->local), "%s", le->device);
err = dst_lookup_device(le->device, &dev);
if (err)
return err;
n->bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
if (!n->bdev)
return -ENODEV;
n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL);
if (IS_ERR(n->bdev))
return PTR_ERR(n->bdev);
if (n->size != 0)
n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size);
@ -528,7 +492,7 @@ static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl,
return 0;
err_out_cleanup:
blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
n->bdev = NULL;
return err;

View file

@ -88,7 +88,7 @@ struct file *anon_inode_getfile(const char *name,
void *priv, int flags)
{
struct qstr this;
struct dentry *dentry;
struct path path;
struct file *file;
int error;
@ -106,10 +106,11 @@ struct file *anon_inode_getfile(const char *name,
this.name = name;
this.len = strlen(name);
this.hash = 0;
dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
if (!dentry)
path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
if (!path.dentry)
goto err_module;
path.mnt = mntget(anon_inode_mnt);
/*
* We know the anon_inode inode count is always greater than zero,
* so we can avoid doing an igrab() and we can use an open-coded
@ -117,14 +118,13 @@ struct file *anon_inode_getfile(const char *name,
*/
atomic_inc(&anon_inode_inode->i_count);
dentry->d_op = &anon_inodefs_dentry_operations;
path.dentry->d_op = &anon_inodefs_dentry_operations;
/* Do not publish this dentry inside the global dentry hash table */
dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(dentry, anon_inode_inode);
path.dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(path.dentry, anon_inode_inode);
error = -ENFILE;
file = alloc_file(anon_inode_mnt, dentry,
FMODE_READ | FMODE_WRITE, fops);
file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
if (!file)
goto err_dput;
file->f_mapping = anon_inode_inode->i_mapping;
@ -137,7 +137,7 @@ struct file *anon_inode_getfile(const char *name,
return file;
err_dput:
dput(dentry);
path_put(&path);
err_module:
module_put(fops->owner);
return ERR_PTR(error);

View file

@ -73,13 +73,13 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
return acl;
}
static int btrfs_xattr_get_acl(struct inode *inode, int type,
void *value, size_t size)
static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
void *value, size_t size, int type)
{
struct posix_acl *acl;
int ret = 0;
acl = btrfs_get_acl(inode, type);
acl = btrfs_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
@ -151,8 +151,8 @@ out:
return ret;
}
static int btrfs_xattr_set_acl(struct inode *inode, int type,
const void *value, size_t size)
static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
int ret = 0;
struct posix_acl *acl = NULL;
@ -167,38 +167,13 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type,
}
}
ret = btrfs_set_acl(inode, acl, type);
ret = btrfs_set_acl(dentry->d_inode, acl, type);
posix_acl_release(acl);
return ret;
}
static int btrfs_xattr_acl_access_get(struct inode *inode, const char *name,
void *value, size_t size)
{
return btrfs_xattr_get_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int btrfs_xattr_acl_access_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return btrfs_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int btrfs_xattr_acl_default_get(struct inode *inode, const char *name,
void *value, size_t size)
{
return btrfs_xattr_get_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
static int btrfs_xattr_acl_default_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return btrfs_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
int btrfs_check_acl(struct inode *inode, int mask)
{
struct posix_acl *acl;
@ -303,14 +278,16 @@ int btrfs_acl_chmod(struct inode *inode)
struct xattr_handler btrfs_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.get = btrfs_xattr_acl_default_get,
.set = btrfs_xattr_acl_default_set,
.flags = ACL_TYPE_DEFAULT,
.get = btrfs_xattr_acl_get,
.set = btrfs_xattr_acl_set,
};
struct xattr_handler btrfs_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.get = btrfs_xattr_acl_access_get,
.set = btrfs_xattr_acl_access_set,
.flags = ACL_TYPE_ACCESS,
.get = btrfs_xattr_acl_get,
.set = btrfs_xattr_acl_set,
};
#else /* CONFIG_BTRFS_FS_POSIX_ACL */

View file

@ -84,7 +84,7 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
{
struct cachefiles_object *fsdef;
struct nameidata nd;
struct path path;
struct kstatfs stats;
struct dentry *graveyard, *cachedir, *root;
const struct cred *saved_cred;
@ -114,15 +114,12 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
_debug("- fsdef %p", fsdef);
/* look up the directory at the root of the cache */
memset(&nd, 0, sizeof(nd));
ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd);
ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
if (ret < 0)
goto error_open_root;
cache->mnt = mntget(nd.path.mnt);
root = dget(nd.path.dentry);
path_put(&nd.path);
cache->mnt = path.mnt;
root = path.dentry;
/* check parameters */
ret = -EOPNOTSUPP;

View file

@ -11,7 +11,6 @@
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/ima.h>
#include "internal.h"
/*
@ -923,7 +922,6 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
if (IS_ERR(file)) {
ret = PTR_ERR(file);
} else {
ima_counts_get(file);
ret = -EIO;
if (file->f_op->write) {
pos = (loff_t) page->index << PAGE_SHIFT;

View file

@ -978,6 +978,7 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
q.hash = full_name_hash(q.name, q.len);
return d_alloc(parent, &q);
}
EXPORT_SYMBOL(d_alloc_name);
/* the caller must hold dcache_lock */
static void __d_instantiate(struct dentry *dentry, struct inode *inode)

View file

@ -35,7 +35,6 @@
#include <linux/key.h>
#include <linux/parser.h>
#include <linux/fs_stack.h>
#include <linux/ima.h>
#include "ecryptfs_kernel.h"
/**
@ -119,7 +118,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
const struct cred *cred = current_cred();
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
int opened_lower_file = 0;
int rc = 0;
mutex_lock(&inode_info->lower_file_mutex);
@ -136,12 +134,9 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
"rc = [%d]\n", lower_dentry, lower_mnt, rc);
inode_info->lower_file = NULL;
} else
opened_lower_file = 1;
}
}
mutex_unlock(&inode_info->lower_file_mutex);
if (opened_lower_file)
ima_counts_get(inode_info->lower_file);
return rc;
}

View file

@ -339,12 +339,12 @@ ext2_acl_chmod(struct inode *inode)
* Extended attribut handlers
*/
static size_t
ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_size)
memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@ -352,12 +352,12 @@ ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
}
static size_t
ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_size)
memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@ -365,15 +365,18 @@ ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
}
static int
ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
struct posix_acl *acl;
int error;
if (!test_opt(inode->i_sb, POSIX_ACL))
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, POSIX_ACL))
return -EOPNOTSUPP;
acl = ext2_get_acl(inode, type);
acl = ext2_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -385,33 +388,17 @@ ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
}
static int
ext2_xattr_get_acl_access(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int
ext2_xattr_get_acl_default(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int
ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
size_t size)
ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int type)
{
struct posix_acl *acl;
int error;
if (!test_opt(inode->i_sb, POSIX_ACL))
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, POSIX_ACL))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
if (!is_owner_or_cap(dentry->d_inode))
return -EPERM;
if (value) {
@ -426,41 +413,25 @@ ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
} else
acl = NULL;
error = ext2_set_acl(inode, type, acl);
error = ext2_set_acl(dentry->d_inode, type, acl);
release_and_out:
posix_acl_release(acl);
return error;
}
static int
ext2_xattr_set_acl_access(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int
ext2_xattr_set_acl_default(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
struct xattr_handler ext2_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.list = ext2_xattr_list_acl_access,
.get = ext2_xattr_get_acl_access,
.set = ext2_xattr_set_acl_access,
.get = ext2_xattr_get_acl,
.set = ext2_xattr_set_acl,
};
struct xattr_handler ext2_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = ext2_xattr_list_acl_default,
.get = ext2_xattr_get_acl_default,
.set = ext2_xattr_set_acl_default,
.get = ext2_xattr_get_acl,
.set = ext2_xattr_set_acl,
};

View file

@ -60,6 +60,7 @@
#include <linux/mbcache.h>
#include <linux/quotaops.h>
#include <linux/rwsem.h>
#include <linux/security.h>
#include "ext2.h"
#include "xattr.h"
#include "acl.h"
@ -249,8 +250,9 @@ cleanup:
* used / required on success.
*/
static int
ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
struct ext2_xattr_entry *entry;
char *end;
@ -300,9 +302,10 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
ext2_xattr_handler(entry->e_name_index);
if (handler) {
size_t size = handler->list(inode, buffer, rest,
size_t size = handler->list(dentry, buffer, rest,
entry->e_name,
entry->e_name_len);
entry->e_name_len,
handler->flags);
if (buffer) {
if (size > rest) {
error = -ERANGE;
@ -330,7 +333,7 @@ cleanup:
ssize_t
ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
{
return ext2_xattr_list(dentry->d_inode, buffer, size);
return ext2_xattr_list(dentry, buffer, size);
}
/*

View file

@ -11,8 +11,8 @@
#include "xattr.h"
static size_t
ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -26,22 +26,22 @@ ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext2_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext2_xattr_security_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
buffer, size);
}
static int
ext2_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext2_xattr_security_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
value, size, flags);
}

View file

@ -13,8 +13,8 @@
#include "xattr.h"
static size_t
ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -31,22 +31,22 @@ ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext2_xattr_trusted_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
buffer, size);
}
static int
ext2_xattr_trusted_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}

View file

@ -12,13 +12,13 @@
#include "xattr.h"
static size_t
ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return 0;
if (list && total_len <= list_size) {
@ -30,27 +30,28 @@ ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext2_xattr_user_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size);
return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_USER,
name, buffer, size);
}
static int
ext2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext2_xattr_user_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
value, size, flags);
return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_USER,
name, value, size, flags);
}
struct xattr_handler ext2_xattr_user_handler = {

View file

@ -366,12 +366,12 @@ out:
* Extended attribute handlers
*/
static size_t
ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@ -379,12 +379,12 @@ ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
}
static size_t
ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@ -392,15 +392,18 @@ ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
}
static int
ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
struct posix_acl *acl;
int error;
if (!test_opt(inode->i_sb, POSIX_ACL))
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, POSIX_ACL))
return -EOPNOTSUPP;
acl = ext3_get_acl(inode, type);
acl = ext3_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -412,31 +415,16 @@ ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
}
static int
ext3_xattr_get_acl_access(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext3_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int
ext3_xattr_get_acl_default(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext3_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int
ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
size_t size)
ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
handle_t *handle;
struct posix_acl *acl;
int error, retries = 0;
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(inode->i_sb, POSIX_ACL))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
@ -468,34 +456,18 @@ release_and_out:
return error;
}
static int
ext3_xattr_set_acl_access(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int
ext3_xattr_set_acl_default(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
struct xattr_handler ext3_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.list = ext3_xattr_list_acl_access,
.get = ext3_xattr_get_acl_access,
.set = ext3_xattr_set_acl_access,
.get = ext3_xattr_get_acl,
.set = ext3_xattr_set_acl,
};
struct xattr_handler ext3_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = ext3_xattr_list_acl_default,
.get = ext3_xattr_get_acl_default,
.set = ext3_xattr_set_acl_default,
.get = ext3_xattr_get_acl,
.set = ext3_xattr_set_acl,
};

View file

@ -99,7 +99,7 @@ static struct buffer_head *ext3_xattr_cache_find(struct inode *,
struct mb_cache_entry **);
static void ext3_xattr_rehash(struct ext3_xattr_header *,
struct ext3_xattr_entry *);
static int ext3_xattr_list(struct inode *inode, char *buffer,
static int ext3_xattr_list(struct dentry *dentry, char *buffer,
size_t buffer_size);
static struct mb_cache *ext3_xattr_cache;
@ -147,7 +147,7 @@ ext3_xattr_handler(int name_index)
ssize_t
ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
{
return ext3_xattr_list(dentry->d_inode, buffer, size);
return ext3_xattr_list(dentry, buffer, size);
}
static int
@ -332,7 +332,7 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
}
static int
ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
char *buffer, size_t buffer_size)
{
size_t rest = buffer_size;
@ -342,9 +342,10 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
ext3_xattr_handler(entry->e_name_index);
if (handler) {
size_t size = handler->list(inode, buffer, rest,
size_t size = handler->list(dentry, buffer, rest,
entry->e_name,
entry->e_name_len);
entry->e_name_len,
handler->flags);
if (buffer) {
if (size > rest)
return -ERANGE;
@ -357,8 +358,9 @@ ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
}
static int
ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
ext3_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
int error;
@ -383,7 +385,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
goto cleanup;
}
ext3_xattr_cache_insert(bh);
error = ext3_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
error = ext3_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
cleanup:
brelse(bh);
@ -392,8 +394,9 @@ cleanup:
}
static int
ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
ext3_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct ext3_xattr_ibody_header *header;
struct ext3_inode *raw_inode;
struct ext3_iloc iloc;
@ -411,7 +414,7 @@ ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
error = ext3_xattr_check_names(IFIRST(header), end);
if (error)
goto cleanup;
error = ext3_xattr_list_entries(inode, IFIRST(header),
error = ext3_xattr_list_entries(dentry, IFIRST(header),
buffer, buffer_size);
cleanup:
@ -430,12 +433,12 @@ cleanup:
* used / required on success.
*/
static int
ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
ext3_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
int i_error, b_error;
down_read(&EXT3_I(inode)->xattr_sem);
i_error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
down_read(&EXT3_I(dentry->d_inode)->xattr_sem);
i_error = ext3_xattr_ibody_list(dentry, buffer, buffer_size);
if (i_error < 0) {
b_error = 0;
} else {
@ -443,11 +446,11 @@ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
buffer += i_error;
buffer_size -= i_error;
}
b_error = ext3_xattr_block_list(inode, buffer, buffer_size);
b_error = ext3_xattr_block_list(dentry, buffer, buffer_size);
if (b_error < 0)
i_error = 0;
}
up_read(&EXT3_I(inode)->xattr_sem);
up_read(&EXT3_I(dentry->d_inode)->xattr_sem);
return i_error + b_error;
}

View file

@ -12,8 +12,8 @@
#include "xattr.h"
static size_t
ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -28,23 +28,23 @@ ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext3_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext3_xattr_security_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name,
buffer, size);
return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
name, buffer, size);
}
static int
ext3_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext3_xattr_security_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
value, size, flags);
return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
name, value, size, flags);
}
int

View file

@ -14,8 +14,8 @@
#include "xattr.h"
static size_t
ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -32,22 +32,22 @@ ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext3_xattr_trusted_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
buffer, size);
return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED,
name, buffer, size);
}
static int
ext3_xattr_trusted_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}

View file

@ -13,13 +13,13 @@
#include "xattr.h"
static size_t
ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return 0;
if (list && total_len <= list_size) {
@ -31,26 +31,27 @@ ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext3_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size);
return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_USER,
name, buffer, size);
}
static int
ext3_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext3_xattr_user_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
value, size, flags);
return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_USER,
name, value, size, flags);
}
struct xattr_handler ext3_xattr_user_handler = {

View file

@ -364,12 +364,12 @@ out:
* Extended attribute handlers
*/
static size_t
ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
ext4_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@ -377,12 +377,12 @@ ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
}
static size_t
ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
ext4_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
const char *name, size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!test_opt(inode->i_sb, POSIX_ACL))
if (!test_opt(dentry->d_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@ -390,15 +390,18 @@ ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
}
static int
ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
ext4_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
struct posix_acl *acl;
int error;
if (!test_opt(inode->i_sb, POSIX_ACL))
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, POSIX_ACL))
return -EOPNOTSUPP;
acl = ext4_get_acl(inode, type);
acl = ext4_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -410,31 +413,16 @@ ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
}
static int
ext4_xattr_get_acl_access(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext4_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int
ext4_xattr_get_acl_default(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext4_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int
ext4_xattr_set_acl(struct inode *inode, int type, const void *value,
size_t size)
ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
handle_t *handle;
struct posix_acl *acl;
int error, retries = 0;
if (strcmp(name, "") != 0)
return -EINVAL;
if (!test_opt(inode->i_sb, POSIX_ACL))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
@ -466,34 +454,18 @@ release_and_out:
return error;
}
static int
ext4_xattr_set_acl_access(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext4_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int
ext4_xattr_set_acl_default(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ext4_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
struct xattr_handler ext4_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.list = ext4_xattr_list_acl_access,
.get = ext4_xattr_get_acl_access,
.set = ext4_xattr_set_acl_access,
.get = ext4_xattr_get_acl,
.set = ext4_xattr_set_acl,
};
struct xattr_handler ext4_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = ext4_xattr_list_acl_default,
.get = ext4_xattr_get_acl_default,
.set = ext4_xattr_set_acl_default,
.get = ext4_xattr_get_acl,
.set = ext4_xattr_set_acl,
};

View file

@ -92,7 +92,7 @@ static struct buffer_head *ext4_xattr_cache_find(struct inode *,
struct mb_cache_entry **);
static void ext4_xattr_rehash(struct ext4_xattr_header *,
struct ext4_xattr_entry *);
static int ext4_xattr_list(struct inode *inode, char *buffer,
static int ext4_xattr_list(struct dentry *dentry, char *buffer,
size_t buffer_size);
static struct mb_cache *ext4_xattr_cache;
@ -140,7 +140,7 @@ ext4_xattr_handler(int name_index)
ssize_t
ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
{
return ext4_xattr_list(dentry->d_inode, buffer, size);
return ext4_xattr_list(dentry, buffer, size);
}
static int
@ -325,7 +325,7 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
}
static int
ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
char *buffer, size_t buffer_size)
{
size_t rest = buffer_size;
@ -335,9 +335,10 @@ ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
ext4_xattr_handler(entry->e_name_index);
if (handler) {
size_t size = handler->list(inode, buffer, rest,
size_t size = handler->list(dentry, buffer, rest,
entry->e_name,
entry->e_name_len);
entry->e_name_len,
handler->flags);
if (buffer) {
if (size > rest)
return -ERANGE;
@ -350,8 +351,9 @@ ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
}
static int
ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
int error;
@ -376,7 +378,7 @@ ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
goto cleanup;
}
ext4_xattr_cache_insert(bh);
error = ext4_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
cleanup:
brelse(bh);
@ -385,8 +387,9 @@ cleanup:
}
static int
ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct ext4_xattr_ibody_header *header;
struct ext4_inode *raw_inode;
struct ext4_iloc iloc;
@ -404,7 +407,7 @@ ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
error = ext4_xattr_check_names(IFIRST(header), end);
if (error)
goto cleanup;
error = ext4_xattr_list_entries(inode, IFIRST(header),
error = ext4_xattr_list_entries(dentry, IFIRST(header),
buffer, buffer_size);
cleanup:
@ -423,12 +426,12 @@ cleanup:
* used / required on success.
*/
static int
ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{
int i_error, b_error;
down_read(&EXT4_I(inode)->xattr_sem);
i_error = ext4_xattr_ibody_list(inode, buffer, buffer_size);
down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
i_error = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
if (i_error < 0) {
b_error = 0;
} else {
@ -436,11 +439,11 @@ ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
buffer += i_error;
buffer_size -= i_error;
}
b_error = ext4_xattr_block_list(inode, buffer, buffer_size);
b_error = ext4_xattr_block_list(dentry, buffer, buffer_size);
if (b_error < 0)
i_error = 0;
}
up_read(&EXT4_I(inode)->xattr_sem);
up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
return i_error + b_error;
}

View file

@ -12,8 +12,8 @@
#include "xattr.h"
static size_t
ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
const size_t total_len = prefix_len + name_len + 1;
@ -28,23 +28,23 @@ ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext4_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext4_xattr_security_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY, name,
buffer, size);
return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
name, buffer, size);
}
static int
ext4_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext4_xattr_security_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY, name,
value, size, flags);
return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
name, value, size, flags);
}
int

View file

@ -14,8 +14,8 @@
#include "xattr.h"
static size_t
ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -32,23 +32,23 @@ ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext4_xattr_trusted_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED, name,
buffer, size);
return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
name, buffer, size);
}
static int
ext4_xattr_trusted_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED, name,
value, size, flags);
return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
name, value, size, flags);
}
struct xattr_handler ext4_xattr_trusted_handler = {

View file

@ -13,13 +13,13 @@
#include "xattr.h"
static size_t
ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return 0;
if (list && total_len <= list_size) {
@ -31,26 +31,27 @@ ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
}
static int
ext4_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
ext4_xattr_user_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER, name, buffer, size);
return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_USER,
name, buffer, size);
}
static int
ext4_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
ext4_xattr_user_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER, name,
value, size, flags);
return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_USER,
name, value, size, flags);
}
struct xattr_handler ext4_xattr_user_handler = {

View file

@ -21,9 +21,12 @@
#include <linux/fsnotify.h>
#include <linux/sysctl.h>
#include <linux/percpu_counter.h>
#include <linux/ima.h>
#include <asm/atomic.h>
#include "internal.h"
/* sysctl tunables... */
struct files_stat_struct files_stat = {
.max_files = NR_FILE
@ -147,8 +150,6 @@ fail:
return NULL;
}
EXPORT_SYMBOL(get_empty_filp);
/**
* alloc_file - allocate and initialize a 'struct file'
* @mnt: the vfsmount on which the file will reside
@ -164,8 +165,8 @@ EXPORT_SYMBOL(get_empty_filp);
* If all the callers of init_file() are eliminated, its
* code should be moved into this function.
*/
struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
fmode_t mode, const struct file_operations *fop)
struct file *alloc_file(struct path *path, fmode_t mode,
const struct file_operations *fop)
{
struct file *file;
@ -173,35 +174,8 @@ struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
if (!file)
return NULL;
init_file(file, mnt, dentry, mode, fop);
return file;
}
EXPORT_SYMBOL(alloc_file);
/**
* init_file - initialize a 'struct file'
* @file: the already allocated 'struct file' to initialized
* @mnt: the vfsmount on which the file resides
* @dentry: the dentry representing this file
* @mode: the mode the file is opened with
* @fop: the 'struct file_operations' for this file
*
* Use this instead of setting the members directly. Doing so
* avoids making mistakes like forgetting the mntget() or
* forgetting to take a write on the mnt.
*
* Note: This is a crappy interface. It is here to make
* merging with the existing users of get_empty_filp()
* who have complex failure logic easier. All users
* of this should be moving to alloc_file().
*/
int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
fmode_t mode, const struct file_operations *fop)
{
int error = 0;
file->f_path.dentry = dentry;
file->f_path.mnt = mntget(mnt);
file->f_mapping = dentry->d_inode->i_mapping;
file->f_path = *path;
file->f_mapping = path->dentry->d_inode->i_mapping;
file->f_mode = mode;
file->f_op = fop;
@ -211,14 +185,15 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
* visible. We do this for consistency, and so
* that we can do debugging checks at __fput()
*/
if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
int error = 0;
file_take_write(file);
error = mnt_clone_write(mnt);
error = mnt_clone_write(path->mnt);
WARN_ON(error);
}
return error;
ima_counts_get(file);
return file;
}
EXPORT_SYMBOL(init_file);
void fput(struct file *file)
{

View file

@ -1,62 +1,58 @@
/*
* fs/generic_acl.c
*
* (C) 2005 Andreas Gruenbacher <agruen@suse.de>
*
* This file is released under the GPL.
*
* Generic ACL support for in-memory filesystems.
*/
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/generic_acl.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
/**
* generic_acl_list - Generic xattr_handler->list() operation
* @ops: Filesystem specific getacl and setacl callbacks
*/
size_t
generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
int type, char *list, size_t list_size)
static size_t
generic_acl_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int type)
{
struct posix_acl *acl;
const char *name;
const char *xname;
size_t size;
acl = ops->getacl(inode, type);
acl = get_cached_acl(dentry->d_inode, type);
if (!acl)
return 0;
posix_acl_release(acl);
switch(type) {
case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
name = POSIX_ACL_XATTR_DEFAULT;
break;
default:
return 0;
switch (type) {
case ACL_TYPE_ACCESS:
xname = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
xname = POSIX_ACL_XATTR_DEFAULT;
break;
default:
return 0;
}
size = strlen(name) + 1;
size = strlen(xname) + 1;
if (list && size <= list_size)
memcpy(list, name, size);
memcpy(list, xname, size);
return size;
}
/**
* generic_acl_get - Generic xattr_handler->get() operation
* @ops: Filesystem specific getacl and setacl callbacks
*/
int
generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
int type, void *buffer, size_t size)
static int
generic_acl_get(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
struct posix_acl *acl;
int error;
acl = ops->getacl(inode, type);
if (strcmp(name, "") != 0)
return -EINVAL;
acl = get_cached_acl(dentry->d_inode, type);
if (!acl)
return -ENODATA;
error = posix_acl_to_xattr(acl, buffer, size);
@ -65,17 +61,16 @@ generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
return error;
}
/**
* generic_acl_set - Generic xattr_handler->set() operation
* @ops: Filesystem specific getacl and setacl callbacks
*/
int
generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
int type, const void *value, size_t size)
static int
generic_acl_set(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl = NULL;
int error;
if (strcmp(name, "") != 0)
return -EINVAL;
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
@ -91,28 +86,27 @@ generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
error = posix_acl_valid(acl);
if (error)
goto failed;
switch(type) {
case ACL_TYPE_ACCESS:
mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
if (error < 0)
goto failed;
inode->i_mode = mode;
if (error == 0) {
posix_acl_release(acl);
acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
if (!S_ISDIR(inode->i_mode)) {
error = -EINVAL;
goto failed;
}
break;
switch (type) {
case ACL_TYPE_ACCESS:
mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
if (error < 0)
goto failed;
inode->i_mode = mode;
if (error == 0) {
posix_acl_release(acl);
acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
if (!S_ISDIR(inode->i_mode)) {
error = -EINVAL;
goto failed;
}
break;
}
}
ops->setacl(inode, type, acl);
set_cached_acl(inode, type, acl);
error = 0;
failed:
posix_acl_release(acl);
@ -121,14 +115,12 @@ failed:
/**
* generic_acl_init - Take care of acl inheritance at @inode create time
* @ops: Filesystem specific getacl and setacl callbacks
*
* Files created inside a directory with a default ACL inherit the
* directory's default ACL.
*/
int
generic_acl_init(struct inode *inode, struct inode *dir,
struct generic_acl_operations *ops)
generic_acl_init(struct inode *inode, struct inode *dir)
{
struct posix_acl *acl = NULL;
mode_t mode = inode->i_mode;
@ -136,7 +128,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
inode->i_mode = mode & ~current_umask();
if (!S_ISLNK(inode->i_mode))
acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
if (acl) {
struct posix_acl *clone;
@ -145,7 +137,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
error = -ENOMEM;
if (!clone)
goto cleanup;
ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
posix_acl_release(clone);
}
clone = posix_acl_clone(acl, GFP_KERNEL);
@ -156,7 +148,7 @@ generic_acl_init(struct inode *inode, struct inode *dir,
if (error >= 0) {
inode->i_mode = mode;
if (error > 0)
ops->setacl(inode, ACL_TYPE_ACCESS, clone);
set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
}
posix_acl_release(clone);
}
@ -169,20 +161,19 @@ cleanup:
/**
* generic_acl_chmod - change the access acl of @inode upon chmod()
* @ops: FIlesystem specific getacl and setacl callbacks
*
* A chmod also changes the permissions of the owner, group/mask, and
* other ACL entries.
*/
int
generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
generic_acl_chmod(struct inode *inode)
{
struct posix_acl *acl, *clone;
int error = 0;
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
acl = ops->getacl(inode, ACL_TYPE_ACCESS);
acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
if (acl) {
clone = posix_acl_clone(acl, GFP_KERNEL);
posix_acl_release(acl);
@ -190,8 +181,37 @@ generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
return -ENOMEM;
error = posix_acl_chmod_masq(clone, inode->i_mode);
if (!error)
ops->setacl(inode, ACL_TYPE_ACCESS, clone);
set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
posix_acl_release(clone);
}
return error;
}
int
generic_check_acl(struct inode *inode, int mask)
{
struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
if (acl) {
int error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
return error;
}
return -EAGAIN;
}
struct xattr_handler generic_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.list = generic_acl_list,
.get = generic_acl_get,
.set = generic_acl_set,
};
struct xattr_handler generic_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = generic_acl_list,
.get = generic_acl_get,
.set = generic_acl_set,
};

View file

@ -126,7 +126,7 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
error = posix_acl_to_xattr(acl, data, len);
if (error < 0)
goto out;
error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, data, len, 0);
error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
if (!error)
set_cached_acl(inode, type, acl);
out:
@ -232,9 +232,10 @@ static int gfs2_acl_type(const char *name)
return -EINVAL;
}
static int gfs2_xattr_system_get(struct inode *inode, const char *name,
void *buffer, size_t size)
static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int xtype)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl;
int type;
int error;
@ -255,9 +256,11 @@ static int gfs2_xattr_system_get(struct inode *inode, const char *name,
return error;
}
static int gfs2_xattr_system_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags,
int xtype)
{
struct inode *inode = dentry->d_inode;
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct posix_acl *acl = NULL;
int error = 0, type;
@ -319,7 +322,7 @@ static int gfs2_xattr_system_set(struct inode *inode, const char *name,
}
set_acl:
error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
if (!error) {
if (acl)
set_cached_acl(inode, type, acl);
@ -334,6 +337,7 @@ out:
struct xattr_handler gfs2_xattr_system_handler = {
.prefix = XATTR_SYSTEM_PREFIX,
.flags = GFS2_EATYPE_SYS,
.get = gfs2_xattr_system_get,
.set = gfs2_xattr_system_set,
};

View file

@ -801,7 +801,8 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
return err;
}
err = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SECURITY, name, value, len, 0);
err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
GFS2_EATYPE_SECURITY);
kfree(value);
kfree(name);

View file

@ -567,18 +567,17 @@ out:
/**
* gfs2_xattr_get - Get a GFS2 extended attribute
* @inode: The inode
* @type: The type of extended attribute
* @name: The name of the extended attribute
* @buffer: The buffer to write the result into
* @size: The size of the buffer
* @type: The type of extended attribute
*
* Returns: actual size of data on success, -errno on error
*/
int gfs2_xattr_get(struct inode *inode, int type, const char *name,
void *buffer, size_t size)
static int gfs2_xattr_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_ea_location el;
int error;
@ -1119,7 +1118,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
/**
* gfs2_xattr_remove - Remove a GFS2 extended attribute
* @inode: The inode
* @ip: The inode
* @type: The type of the extended attribute
* @name: The name of the extended attribute
*
@ -1130,9 +1129,8 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
* Returns: 0, or errno on failure
*/
static int gfs2_xattr_remove(struct inode *inode, int type, const char *name)
static int gfs2_xattr_remove(struct gfs2_inode *ip, int type, const char *name)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_ea_location el;
int error;
@ -1156,24 +1154,24 @@ static int gfs2_xattr_remove(struct inode *inode, int type, const char *name)
}
/**
* gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
* @inode: The inode
* @type: The type of the extended attribute
* __gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
* @ip: The inode
* @name: The name of the extended attribute
* @value: The value of the extended attribute (NULL for remove)
* @size: The size of the @value argument
* @flags: Create or Replace
* @type: The type of the extended attribute
*
* See gfs2_xattr_remove() for details of the removal of xattrs.
*
* Returns: 0 or errno on failure
*/
int gfs2_xattr_set(struct inode *inode, int type, const char *name,
const void *value, size_t size, int flags)
int __gfs2_xattr_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags, int type)
{
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_ea_location el;
unsigned int namel = strlen(name);
int error;
@ -1184,7 +1182,7 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name,
return -ERANGE;
if (value == NULL)
return gfs2_xattr_remove(inode, type, name);
return gfs2_xattr_remove(ip, type, name);
if (ea_check_size(sdp, namel, size))
return -ERANGE;
@ -1224,6 +1222,13 @@ int gfs2_xattr_set(struct inode *inode, int type, const char *name,
return error;
}
static int gfs2_xattr_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
return __gfs2_xattr_set(dentry->d_inode, name, value,
size, flags, type);
}
static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
struct gfs2_ea_header *ea, char *data)
{
@ -1529,40 +1534,18 @@ out_alloc:
return error;
}
static int gfs2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
return gfs2_xattr_get(inode, GFS2_EATYPE_USR, name, buffer, size);
}
static int gfs2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
}
static int gfs2_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
return gfs2_xattr_get(inode, GFS2_EATYPE_SECURITY, name, buffer, size);
}
static int gfs2_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return gfs2_xattr_set(inode, GFS2_EATYPE_SECURITY, name, value, size, flags);
}
static struct xattr_handler gfs2_xattr_user_handler = {
.prefix = XATTR_USER_PREFIX,
.get = gfs2_xattr_user_get,
.set = gfs2_xattr_user_set,
.flags = GFS2_EATYPE_USR,
.get = gfs2_xattr_get,
.set = gfs2_xattr_set,
};
static struct xattr_handler gfs2_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = gfs2_xattr_security_get,
.set = gfs2_xattr_security_set,
.flags = GFS2_EATYPE_SECURITY,
.get = gfs2_xattr_get,
.set = gfs2_xattr_set,
};
struct xattr_handler *gfs2_xattr_handlers[] = {

View file

@ -53,10 +53,9 @@ struct gfs2_ea_location {
struct gfs2_ea_header *el_prev;
};
extern int gfs2_xattr_get(struct inode *inode, int type, const char *name,
void *buffer, size_t size);
extern int gfs2_xattr_set(struct inode *inode, int type, const char *name,
const void *value, size_t size, int flags);
extern int __gfs2_xattr_set(struct inode *inode, const char *name,
const void *value, size_t size,
int flags, int type);
extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size);
extern int gfs2_ea_dealloc(struct gfs2_inode *ip);

View file

@ -30,7 +30,6 @@
#include <linux/dnotify.h>
#include <linux/statfs.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/magic.h>
#include <asm/uaccess.h>
@ -922,7 +921,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
int error = -ENOMEM;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct path path;
struct dentry *root;
struct qstr quick_string;
*user = NULL;
@ -944,10 +944,11 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
quick_string.name = name;
quick_string.len = strlen(quick_string.name);
quick_string.hash = 0;
dentry = d_alloc(root, &quick_string);
if (!dentry)
path.dentry = d_alloc(root, &quick_string);
if (!path.dentry)
goto out_shm_unlock;
path.mnt = mntget(hugetlbfs_vfsmount);
error = -ENOSPC;
inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
current_fsgid(), S_IFREG | S_IRWXUGO, 0);
@ -960,24 +961,22 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
acctflag))
goto out_inode;
d_instantiate(dentry, inode);
d_instantiate(path.dentry, inode);
inode->i_size = size;
inode->i_nlink = 0;
error = -ENFILE;
file = alloc_file(hugetlbfs_vfsmount, dentry,
FMODE_WRITE | FMODE_READ,
file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
&hugetlbfs_file_operations);
if (!file)
goto out_dentry; /* inode is already attached */
ima_counts_get(file);
return file;
out_inode:
iput(inode);
out_dentry:
dput(dentry);
path_put(&path);
out_shm_unlock:
if (*user) {
user_shm_unlock(size, *user);

View file

@ -79,6 +79,7 @@ extern void chroot_fs_refs(struct path *, struct path *);
* file_table.c
*/
extern void mark_files_ro(struct super_block *);
extern struct file *get_empty_filp(void);
/*
* super.c

View file

@ -350,8 +350,8 @@ int jffs2_acl_chmod(struct inode *inode)
return rc;
}
static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t jffs2_acl_access_listxattr(struct dentry *dentry, char *list,
size_t list_size, const char *name, size_t name_len, int type)
{
const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
@ -360,8 +360,8 @@ static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t
return retlen;
}
static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t jffs2_acl_default_listxattr(struct dentry *dentry, char *list,
size_t list_size, const char *name, size_t name_len, int type)
{
const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
@ -370,12 +370,16 @@ static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_
return retlen;
}
static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
static int jffs2_acl_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
struct posix_acl *acl;
int rc;
acl = jffs2_get_acl(inode, type);
if (name[0] != '\0')
return -EINVAL;
acl = jffs2_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (!acl)
@ -386,26 +390,15 @@ static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_
return rc;
}
static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
{
if (name[0] != '\0')
return -EINVAL;
return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
{
if (name[0] != '\0')
return -EINVAL;
return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
static int jffs2_acl_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
struct posix_acl *acl;
int rc;
if (!is_owner_or_cap(inode))
if (name[0] != '\0')
return -EINVAL;
if (!is_owner_or_cap(dentry->d_inode))
return -EPERM;
if (value) {
@ -420,38 +413,24 @@ static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value,
} else {
acl = NULL;
}
rc = jffs2_set_acl(inode, type, acl);
rc = jffs2_set_acl(dentry->d_inode, type, acl);
out:
posix_acl_release(acl);
return rc;
}
static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
const void *buffer, size_t size, int flags)
{
if (name[0] != '\0')
return -EINVAL;
return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
const void *buffer, size_t size, int flags)
{
if (name[0] != '\0')
return -EINVAL;
return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
}
struct xattr_handler jffs2_acl_access_xattr_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_DEFAULT,
.list = jffs2_acl_access_listxattr,
.get = jffs2_acl_access_getxattr,
.set = jffs2_acl_access_setxattr,
.get = jffs2_acl_getxattr,
.set = jffs2_acl_setxattr,
};
struct xattr_handler jffs2_acl_default_xattr_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = jffs2_acl_default_listxattr,
.get = jffs2_acl_default_getxattr,
.set = jffs2_acl_default_setxattr,
.get = jffs2_acl_getxattr,
.set = jffs2_acl_setxattr,
};

View file

@ -44,26 +44,28 @@ int jffs2_init_security(struct inode *inode, struct inode *dir)
}
/* ---- XATTR Handler for "security.*" ----------------- */
static int jffs2_security_getxattr(struct inode *inode, const char *name,
void *buffer, size_t size)
static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
name, buffer, size);
}
static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
name, buffer, size, flags);
}
static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
size_t list_size, const char *name, size_t name_len, int type)
{
size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;

View file

@ -990,9 +990,11 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
if (!xhandle)
continue;
if (buffer) {
rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
rc = xhandle->list(dentry, buffer+len, size-len,
xd->xname, xd->name_len, xd->flags);
} else {
rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
rc = xhandle->list(dentry, NULL, 0, xd->xname,
xd->name_len, xd->flags);
}
if (rc < 0)
goto out;

View file

@ -16,24 +16,26 @@
#include <linux/mtd/mtd.h>
#include "nodelist.h"
static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
void *buffer, size_t size)
static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
name, buffer, size);
}
static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
name, buffer, size, flags);
}
static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
size_t list_size, const char *name, size_t name_len, int type)
{
size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;

View file

@ -16,24 +16,26 @@
#include <linux/mtd/mtd.h>
#include "nodelist.h"
static int jffs2_user_getxattr(struct inode *inode, const char *name,
void *buffer, size_t size)
static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
name, buffer, size);
}
static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags, int type)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
name, buffer, size, flags);
}
static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
size_t list_size, const char *name, size_t name_len, int type)
{
size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;

View file

@ -848,7 +848,6 @@ EXPORT_SYMBOL(simple_write_end);
EXPORT_SYMBOL(simple_dir_inode_operations);
EXPORT_SYMBOL(simple_dir_operations);
EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(d_alloc_name);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(simple_getattr);
EXPORT_SYMBOL(simple_link);

View file

@ -35,6 +35,8 @@
#include <linux/fs_struct.h>
#include <asm/uaccess.h>
#include "internal.h"
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
/* [Feb-1997 T. Schoebel-Theuer]
@ -108,8 +110,6 @@
* any extra contention...
*/
static int __link_path_walk(const char *name, struct nameidata *nd);
/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
@ -414,36 +414,55 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
}
/*
* Internal lookup() using the new generic dcache.
* SMP-safe
* force_reval_path - force revalidation of a dentry
*
* In some situations the path walking code will trust dentries without
* revalidating them. This causes problems for filesystems that depend on
* d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set
* (which indicates that it's possible for the dentry to go stale), force
* a d_revalidate call before proceeding.
*
* Returns 0 if the revalidation was successful. If the revalidation fails,
* either return the error returned by d_revalidate or -ESTALE if the
* revalidation it just returned 0. If d_revalidate returns 0, we attempt to
* invalidate the dentry. It's up to the caller to handle putting references
* to the path if necessary.
*/
static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
static int
force_reval_path(struct path *path, struct nameidata *nd)
{
struct dentry * dentry = __d_lookup(parent, name);
int status;
struct dentry *dentry = path->dentry;
/* lockess __d_lookup may fail due to concurrent d_move()
* in some unrelated directory, so try with d_lookup
/*
* only check on filesystems where it's possible for the dentry to
* become stale. It's assumed that if this flag is set then the
* d_revalidate op will also be defined.
*/
if (!dentry)
dentry = d_lookup(parent, name);
if (!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))
return 0;
if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
dentry = do_revalidate(dentry, nd);
status = dentry->d_op->d_revalidate(dentry, nd);
if (status > 0)
return 0;
return dentry;
if (!status) {
d_invalidate(dentry);
status = -ESTALE;
}
return status;
}
/*
* Short-cut version of permission(), for calling by
* path_walk(), when dcache lock is held. Combines parts
* of permission() and generic_permission(), and tests ONLY for
* MAY_EXEC permission.
* Short-cut version of permission(), for calling on directories
* during pathname resolution. Combines parts of permission()
* and generic_permission(), and tests ONLY for MAY_EXEC permission.
*
* If appropriate, check DAC only. If not appropriate, or
* short-cut DAC fails, then call permission() to do more
* short-cut DAC fails, then call ->permission() to do more
* complete permission check.
*/
static int exec_permission_lite(struct inode *inode)
static int exec_permission(struct inode *inode)
{
int ret;
@ -465,99 +484,6 @@ ok:
return security_inode_permission(inode, MAY_EXEC);
}
/*
* This is called when everything else fails, and we actually have
* to go to the low-level filesystem to find out what we should do..
*
* We get the directory semaphore, and after getting that we also
* make sure that nobody added the entry to the dcache in the meantime..
* SMP-safe
*/
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
mutex_lock(&dir->i_mutex);
/*
* First re-do the cached lookup just in case it was created
* while we waited for the directory semaphore..
*
* FIXME! This could use version numbering or similar to
* avoid unnecessary cache lookups.
*
* The "dcache_lock" is purely to protect the RCU list walker
* from concurrent renames at this point (we mustn't get false
* negatives from the RCU list walk here, unlike the optimistic
* fast walk).
*
* so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
*/
result = d_lookup(parent, name);
if (!result) {
struct dentry *dentry;
/* Don't create child dentry for a dead directory. */
result = ERR_PTR(-ENOENT);
if (IS_DEADDIR(dir))
goto out_unlock;
dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
result = dir->i_op->lookup(dir, dentry, nd);
if (result)
dput(dentry);
else
result = dentry;
}
out_unlock:
mutex_unlock(&dir->i_mutex);
return result;
}
/*
* Uhhuh! Nasty case: the cache was re-populated while
* we waited on the semaphore. Need to revalidate.
*/
mutex_unlock(&dir->i_mutex);
if (result->d_op && result->d_op->d_revalidate) {
result = do_revalidate(result, nd);
if (!result)
result = ERR_PTR(-ENOENT);
}
return result;
}
/*
* Wrapper to retry pathname resolution whenever the underlying
* file system returns an ESTALE.
*
* Retry the whole path once, forcing real lookup requests
* instead of relying on the dcache.
*/
static __always_inline int link_path_walk(const char *name, struct nameidata *nd)
{
struct path save = nd->path;
int result;
/* make sure the stuff we saved doesn't go away */
path_get(&save);
result = __link_path_walk(name, nd);
if (result == -ESTALE) {
/* nd->path had been dropped */
nd->path = save;
path_get(&nd->path);
nd->flags |= LOOKUP_REVAL;
result = __link_path_walk(name, nd);
}
path_put(&save);
return result;
}
static __always_inline void set_root(struct nameidata *nd)
{
if (!nd->root.mnt) {
@ -569,6 +495,8 @@ static __always_inline void set_root(struct nameidata *nd)
}
}
static int link_path_walk(const char *, struct nameidata *);
static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
@ -641,11 +569,14 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
error = 0;
if (s)
error = __vfs_follow_link(nd, s);
else if (nd->last_type == LAST_BIND) {
error = force_reval_path(&nd->path, nd);
if (error)
path_put(&nd->path);
}
if (dentry->d_inode->i_op->put_link)
dentry->d_inode->i_op->put_link(dentry, nd, cookie);
}
path_put(path);
return error;
}
@ -672,6 +603,7 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
current->total_link_count++;
nd->depth++;
err = __do_follow_link(path, nd);
path_put(path);
current->link_count--;
nd->depth--;
return err;
@ -797,8 +729,19 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
struct path *path)
{
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry = __d_lookup(nd->path.dentry, name);
struct dentry *dentry, *parent;
struct inode *dir;
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
if (err < 0)
return err;
}
dentry = __d_lookup(nd->path.dentry, name);
if (!dentry)
goto need_lookup;
if (dentry->d_op && dentry->d_op->d_revalidate)
@ -810,7 +753,59 @@ done:
return 0;
need_lookup:
dentry = real_lookup(nd->path.dentry, name, nd);
parent = nd->path.dentry;
dir = parent->d_inode;
mutex_lock(&dir->i_mutex);
/*
* First re-do the cached lookup just in case it was created
* while we waited for the directory semaphore..
*
* FIXME! This could use version numbering or similar to
* avoid unnecessary cache lookups.
*
* The "dcache_lock" is purely to protect the RCU list walker
* from concurrent renames at this point (we mustn't get false
* negatives from the RCU list walk here, unlike the optimistic
* fast walk).
*
* so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
*/
dentry = d_lookup(parent, name);
if (!dentry) {
struct dentry *new;
/* Don't create child dentry for a dead directory. */
dentry = ERR_PTR(-ENOENT);
if (IS_DEADDIR(dir))
goto out_unlock;
new = d_alloc(parent, name);
dentry = ERR_PTR(-ENOMEM);
if (new) {
dentry = dir->i_op->lookup(dir, new, nd);
if (dentry)
dput(new);
else
dentry = new;
}
out_unlock:
mutex_unlock(&dir->i_mutex);
if (IS_ERR(dentry))
goto fail;
goto done;
}
/*
* Uhhuh! Nasty case: the cache was re-populated while
* we waited on the semaphore. Need to revalidate.
*/
mutex_unlock(&dir->i_mutex);
if (dentry->d_op && dentry->d_op->d_revalidate) {
dentry = do_revalidate(dentry, nd);
if (!dentry)
dentry = ERR_PTR(-ENOENT);
}
if (IS_ERR(dentry))
goto fail;
goto done;
@ -835,7 +830,7 @@ fail:
* Returns 0 and nd will have valid dentry and mnt on success.
* Returns error and drops reference to input namei data on failure.
*/
static int __link_path_walk(const char *name, struct nameidata *nd)
static int link_path_walk(const char *name, struct nameidata *nd)
{
struct path next;
struct inode *inode;
@ -858,7 +853,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
unsigned int c;
nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode);
err = exec_permission(inode);
if (err)
break;
@ -898,16 +893,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
case 1:
continue;
}
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
&this);
if (err < 0)
break;
}
/* This does the actual lookups.. */
err = do_lookup(nd, &this, &next);
if (err)
@ -953,12 +938,6 @@ last_component:
case 1:
goto return_reval;
}
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
&this);
if (err < 0)
break;
}
err = do_lookup(nd, &this, &next);
if (err)
break;
@ -1017,8 +996,27 @@ return_err:
static int path_walk(const char *name, struct nameidata *nd)
{
struct path save = nd->path;
int result;
current->total_link_count = 0;
return link_path_walk(name, nd);
/* make sure the stuff we saved doesn't go away */
path_get(&save);
result = link_path_walk(name, nd);
if (result == -ESTALE) {
/* nd->path had been dropped */
current->total_link_count = 0;
nd->path = save;
path_get(&nd->path);
nd->flags |= LOOKUP_REVAL;
result = link_path_walk(name, nd);
}
path_put(&save);
return result;
}
static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
@ -1141,36 +1139,6 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
return retval;
}
/**
* path_lookup_open - lookup a file path with open intent
* @dfd: the directory to use as base, or AT_FDCWD
* @name: pointer to file name
* @lookup_flags: lookup intent flags
* @nd: pointer to nameidata
* @open_flags: open intent flags
*/
static int path_lookup_open(int dfd, const char *name,
unsigned int lookup_flags, struct nameidata *nd, int open_flags)
{
struct file *filp = get_empty_filp();
int err;
if (filp == NULL)
return -ENFILE;
nd->intent.open.file = filp;
nd->intent.open.flags = open_flags;
nd->intent.open.create_mode = 0;
err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
if (IS_ERR(nd->intent.open.file)) {
if (err == 0) {
err = PTR_ERR(nd->intent.open.file);
path_put(&nd->path);
}
} else if (err != 0)
release_open_intent(nd);
return err;
}
static struct dentry *__lookup_hash(struct qstr *name,
struct dentry *base, struct nameidata *nd)
{
@ -1191,7 +1159,17 @@ static struct dentry *__lookup_hash(struct qstr *name,
goto out;
}
dentry = cached_lookup(base, name, nd);
dentry = __d_lookup(base, name);
/* lockess __d_lookup may fail due to concurrent d_move()
* in some unrelated directory, so try with d_lookup
*/
if (!dentry)
dentry = d_lookup(base, name);
if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
dentry = do_revalidate(dentry, nd);
if (!dentry) {
struct dentry *new;
@ -1223,7 +1201,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
{
int err;
err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
err = exec_permission(nd->path.dentry->d_inode);
if (err)
return ERR_PTR(err);
return __lookup_hash(&nd->last, nd->path.dentry, nd);
@ -1273,7 +1251,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
if (err)
return ERR_PTR(err);
err = inode_permission(base->d_inode, MAY_EXEC);
err = exec_permission(base->d_inode);
if (err)
return ERR_PTR(err);
return __lookup_hash(&this, base, NULL);
@ -1511,69 +1489,45 @@ int may_open(struct path *path, int acc_mode, int flag)
if (error)
return error;
error = ima_path_check(path, acc_mode ?
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
ACC_MODE(flag) & (MAY_READ | MAY_WRITE),
IMA_COUNT_UPDATE);
if (error)
return error;
/*
* An append-only file must be opened in append mode for writing.
*/
if (IS_APPEND(inode)) {
error = -EPERM;
if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
goto err_out;
return -EPERM;
if (flag & O_TRUNC)
goto err_out;
return -EPERM;
}
/* O_NOATIME can only be set by the owner or superuser */
if (flag & O_NOATIME)
if (!is_owner_or_cap(inode)) {
error = -EPERM;
goto err_out;
}
if (flag & O_NOATIME && !is_owner_or_cap(inode))
return -EPERM;
/*
* Ensure there are no outstanding leases on the file.
*/
error = break_lease(inode, flag);
return break_lease(inode, flag);
}
static int handle_truncate(struct path *path)
{
struct inode *inode = path->dentry->d_inode;
int error = get_write_access(inode);
if (error)
goto err_out;
if (flag & O_TRUNC) {
error = get_write_access(inode);
if (error)
goto err_out;
/*
* Refuse to truncate files with mandatory locks held on them.
*/
error = locks_verify_locked(inode);
if (!error)
error = security_path_truncate(path, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
if (!error) {
vfs_dq_init(inode);
error = do_truncate(dentry, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
NULL);
}
put_write_access(inode);
if (error)
goto err_out;
} else
if (flag & FMODE_WRITE)
vfs_dq_init(inode);
return 0;
err_out:
ima_counts_put(path, acc_mode ?
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
ACC_MODE(flag) & (MAY_READ | MAY_WRITE));
return error;
/*
* Refuse to truncate files with mandatory locks held on them.
*/
error = locks_verify_locked(inode);
if (!error)
error = security_path_truncate(path, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
if (!error) {
error = do_truncate(path->dentry, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
NULL);
}
put_write_access(inode);
return error;
}
@ -1628,7 +1582,7 @@ static inline int open_to_namei_flags(int flag)
return flag;
}
static int open_will_write_to_fs(int flag, struct inode *inode)
static int open_will_truncate(int flag, struct inode *inode)
{
/*
* We'll never write to the fs underlying
@ -1650,10 +1604,10 @@ struct file *do_filp_open(int dfd, const char *pathname,
struct file *filp;
struct nameidata nd;
int error;
struct path path;
struct path path, save;
struct dentry *dir;
int count = 0;
int will_write;
int will_truncate;
int flag = open_to_namei_flags(open_flag);
/*
@ -1681,8 +1635,22 @@ struct file *do_filp_open(int dfd, const char *pathname,
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
error = path_lookup_open(dfd, pathname, lookup_flags(flag),
&nd, flag);
filp = get_empty_filp();
if (filp == NULL)
return ERR_PTR(-ENFILE);
nd.intent.open.file = filp;
nd.intent.open.flags = flag;
nd.intent.open.create_mode = 0;
error = do_path_lookup(dfd, pathname,
lookup_flags(flag)|LOOKUP_OPEN, &nd);
if (IS_ERR(nd.intent.open.file)) {
if (error == 0) {
error = PTR_ERR(nd.intent.open.file);
path_put(&nd.path);
}
} else if (error)
release_open_intent(&nd);
if (error)
return ERR_PTR(error);
goto ok;
@ -1758,13 +1726,17 @@ do_last:
goto exit;
}
filp = nameidata_to_filp(&nd, open_flag);
if (IS_ERR(filp))
ima_counts_put(&nd.path,
acc_mode & (MAY_READ | MAY_WRITE |
MAY_EXEC));
mnt_drop_write(nd.path.mnt);
if (nd.root.mnt)
path_put(&nd.root);
if (!IS_ERR(filp)) {
error = ima_path_check(&filp->f_path, filp->f_mode &
(MAY_READ | MAY_WRITE | MAY_EXEC));
if (error) {
fput(filp);
filp = ERR_PTR(error);
}
}
return filp;
}
@ -1805,28 +1777,45 @@ ok:
* be avoided. Taking this mnt write here
* ensures that (2) can not occur.
*/
will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
if (will_write) {
will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode);
if (will_truncate) {
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit;
}
error = may_open(&nd.path, acc_mode, flag);
if (error) {
if (will_write)
if (will_truncate)
mnt_drop_write(nd.path.mnt);
goto exit;
}
filp = nameidata_to_filp(&nd, open_flag);
if (IS_ERR(filp))
ima_counts_put(&nd.path,
acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
if (!IS_ERR(filp)) {
error = ima_path_check(&filp->f_path, filp->f_mode &
(MAY_READ | MAY_WRITE | MAY_EXEC));
if (error) {
fput(filp);
filp = ERR_PTR(error);
}
}
if (!IS_ERR(filp)) {
if (acc_mode & MAY_WRITE)
vfs_dq_init(nd.path.dentry->d_inode);
if (will_truncate) {
error = handle_truncate(&nd.path);
if (error) {
fput(filp);
filp = ERR_PTR(error);
}
}
}
/*
* It is now safe to drop the mnt write
* because the filp has had a write taken
* on its behalf.
*/
if (will_write)
if (will_truncate)
mnt_drop_write(nd.path.mnt);
if (nd.root.mnt)
path_put(&nd.root);
@ -1863,7 +1852,18 @@ do_link:
error = security_inode_follow_link(path.dentry, &nd);
if (error)
goto exit_dput;
save = nd.path;
path_get(&save);
error = __do_follow_link(&path, &nd);
if (error == -ESTALE) {
/* nd.path had been dropped */
nd.path = save;
path_get(&nd.path);
nd.flags |= LOOKUP_REVAL;
error = __do_follow_link(&path, &nd);
}
path_put(&save);
path_put(&path);
if (error) {
/* Does someone understand code flow here? Or it is only
* me so stupid? Anathema to whoever designed this non-sense

View file

@ -2068,7 +2068,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
* create_mnt_ns - creates a private namespace and adds a root filesystem
* @mnt: pointer to the new root filesystem mountpoint
*/
struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
{
struct mnt_namespace *new_ns;
@ -2080,7 +2080,6 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
}
return new_ns;
}
EXPORT_SYMBOL(create_mnt_ns);
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)

View file

@ -2648,21 +2648,13 @@ out_freepage:
static int nfs_follow_remote_path(struct vfsmount *root_mnt,
const char *export_path, struct vfsmount *mnt_target)
{
struct mnt_namespace *ns_private;
struct nameidata nd;
struct super_block *s;
int ret;
ns_private = create_mnt_ns(root_mnt);
ret = PTR_ERR(ns_private);
if (IS_ERR(ns_private))
goto out_mntput;
ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
export_path, LOOKUP_FOLLOW, &nd);
put_mnt_ns(ns_private);
if (ret != 0)
goto out_err;

View file

@ -752,8 +752,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
flags, current_cred());
if (IS_ERR(*filp))
host_err = PTR_ERR(*filp);
else
ima_counts_get(*filp);
out_nfserr:
err = nfserrno(host_err);
out:
@ -2132,8 +2130,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
*/
path.mnt = exp->ex_path.mnt;
path.dentry = dentry;
err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
IMA_COUNT_LEAVE);
err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
nfsd_out:
return err? nfserrno(err) : 0;
}

View file

@ -1118,8 +1118,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
/* Abandoning the newly allocated superblock */
mutex_unlock(&nilfs->ns_mount_mutex);
put_nilfs(nilfs);
up_write(&s->s_umount);
deactivate_super(s);
deactivate_locked_super(s);
/*
* deactivate_super() invokes close_bdev_exclusive().
* We must finish all post-cleaning before this call;

View file

@ -646,6 +646,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
struct fsnotify_group *group;
struct user_struct *user;
struct file *filp;
struct path path;
int fd, ret;
/* Check the IN_* constants for consistency. */
@ -659,12 +660,6 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
if (fd < 0)
return fd;
filp = get_empty_filp();
if (!filp) {
ret = -ENFILE;
goto out_put_fd;
}
user = get_current_user();
if (unlikely(atomic_read(&user->inotify_devs) >=
inotify_max_user_instances)) {
@ -679,24 +674,28 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
goto out_free_uid;
}
filp->f_op = &inotify_fops;
filp->f_path.mnt = mntget(inotify_mnt);
filp->f_path.dentry = dget(inotify_mnt->mnt_root);
filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
filp->f_mode = FMODE_READ;
atomic_inc(&user->inotify_devs);
path.mnt = inotify_mnt;
path.dentry = inotify_mnt->mnt_root;
path_get(&path);
filp = alloc_file(&path, FMODE_READ, &inotify_fops);
if (!filp)
goto Enfile;
filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
filp->private_data = group;
atomic_inc(&user->inotify_devs);
fd_install(fd, filp);
return fd;
Enfile:
ret = -ENFILE;
path_put(&path);
atomic_dec(&user->inotify_devs);
out_free_uid:
free_uid(user);
put_filp(filp);
out_put_fd:
put_unused_fd(fd);
return ret;
}

View file

@ -331,13 +331,14 @@ cleanup:
return ret;
}
static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry,
char *list,
size_t list_len,
const char *name,
size_t name_len)
size_t name_len,
int type)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@ -348,13 +349,14 @@ static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
return size;
}
static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry,
char *list,
size_t list_len,
const char *name,
size_t name_len)
size_t name_len,
int type)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@ -365,19 +367,19 @@ static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
return size;
}
static int ocfs2_xattr_get_acl(struct inode *inode,
int type,
void *buffer,
size_t size)
static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
struct posix_acl *acl;
int ret;
if (strcmp(name, "") != 0)
return -EINVAL;
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
return -EOPNOTSUPP;
acl = ocfs2_get_acl(inode, type);
acl = ocfs2_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -388,35 +390,16 @@ static int ocfs2_xattr_get_acl(struct inode *inode,
return ret;
}
static int ocfs2_xattr_get_acl_access(struct inode *inode,
const char *name,
void *buffer,
size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int ocfs2_xattr_get_acl_default(struct inode *inode,
const char *name,
void *buffer,
size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int ocfs2_xattr_set_acl(struct inode *inode,
int type,
const void *value,
size_t size)
static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct posix_acl *acl;
int ret = 0;
if (strcmp(name, "") != 0)
return -EINVAL;
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
return -EOPNOTSUPP;
@ -442,38 +425,18 @@ cleanup:
return ret;
}
static int ocfs2_xattr_set_acl_access(struct inode *inode,
const char *name,
const void *value,
size_t size,
int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static int ocfs2_xattr_set_acl_default(struct inode *inode,
const char *name,
const void *value,
size_t size,
int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
struct xattr_handler ocfs2_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.list = ocfs2_xattr_list_acl_access,
.get = ocfs2_xattr_get_acl_access,
.set = ocfs2_xattr_set_acl_access,
.get = ocfs2_xattr_get_acl,
.set = ocfs2_xattr_set_acl,
};
struct xattr_handler ocfs2_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.list = ocfs2_xattr_list_acl_default,
.get = ocfs2_xattr_get_acl_default,
.set = ocfs2_xattr_set_acl_default,
.get = ocfs2_xattr_get_acl,
.set = ocfs2_xattr_set_acl,
};

View file

@ -7190,8 +7190,8 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
* wait on them - the truncate_inode_pages() call later will
* do that for us.
*/
ret = do_sync_mapping_range(inode->i_mapping, range_start,
range_end - 1, SYNC_FILE_RANGE_WRITE);
ret = filemap_fdatawrite_range(inode->i_mapping, range_start,
range_end - 1);
if (ret)
mlog_errno(ret);

View file

@ -205,8 +205,6 @@ static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
int offset,
struct ocfs2_xattr_value_root **xv,
struct buffer_head **bh);
static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags);
static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
{
@ -6978,9 +6976,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,
ret = ocfs2_init_security_get(inode, dir, &si);
if (!ret) {
ret = ocfs2_xattr_security_set(inode, si.name,
si.value, si.value_len,
XATTR_CREATE);
ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
si.name, si.value, si.value_len,
XATTR_CREATE);
if (ret) {
mlog_errno(ret);
goto leave;
@ -7008,9 +7006,9 @@ leave:
/*
* 'security' attributes support
*/
static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
size_t list_size, const char *name,
size_t name_len)
size_t name_len, int type)
{
const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -7023,23 +7021,23 @@ static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
return total_len;
}
static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY, name,
buffer, size);
return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
name, buffer, size);
}
static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, name, value,
size, flags);
return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
name, value, size, flags);
}
int ocfs2_init_security_get(struct inode *inode,
@ -7076,9 +7074,9 @@ struct xattr_handler ocfs2_xattr_security_handler = {
/*
* 'trusted' attributes support
*/
static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
size_t list_size, const char *name,
size_t name_len)
size_t name_len, int type)
{
const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
@ -7091,23 +7089,23 @@ static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
return total_len;
}
static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
void *buffer, size_t size)
static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED, name,
buffer, size);
return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
name, buffer, size);
}
static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED, name, value,
size, flags);
return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
name, value, size, flags);
}
struct xattr_handler ocfs2_xattr_trusted_handler = {
@ -7120,13 +7118,13 @@ struct xattr_handler ocfs2_xattr_trusted_handler = {
/*
* 'user' attributes support
*/
static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
size_t list_size, const char *name,
size_t name_len)
size_t name_len, int type)
{
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
return 0;
@ -7139,31 +7137,31 @@ static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
return total_len;
}
static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
if (strcmp(name, "") == 0)
return -EINVAL;
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
return -EOPNOTSUPP;
return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_USER, name,
buffer, size);
}
static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
if (strcmp(name, "") == 0)
return -EINVAL;
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
return -EOPNOTSUPP;
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER, name, value,
size, flags);
return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_USER,
name, value, size, flags);
}
struct xattr_handler ocfs2_xattr_user_handler = {

View file

@ -30,6 +30,9 @@
#include <linux/audit.h>
#include <linux/falloc.h>
#include <linux/fs_struct.h>
#include <linux/ima.h>
#include "internal.h"
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
@ -855,6 +858,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
if (error)
goto cleanup_all;
}
ima_counts_get(f);
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

View file

@ -974,7 +974,7 @@ struct file *create_write_pipe(int flags)
int err;
struct inode *inode;
struct file *f;
struct dentry *dentry;
struct path path;
struct qstr name = { .name = "" };
err = -ENFILE;
@ -983,21 +983,22 @@ struct file *create_write_pipe(int flags)
goto err;
err = -ENOMEM;
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
if (!dentry)
path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
if (!path.dentry)
goto err_inode;
path.mnt = mntget(pipe_mnt);
dentry->d_op = &pipefs_dentry_operations;
path.dentry->d_op = &pipefs_dentry_operations;
/*
* We dont want to publish this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on pipes
*/
dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(dentry, inode);
path.dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(path.dentry, inode);
err = -ENFILE;
f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops);
if (!f)
goto err_dentry;
f->f_mapping = inode->i_mapping;
@ -1009,7 +1010,7 @@ struct file *create_write_pipe(int flags)
err_dentry:
free_pipe_info(inode);
dput(dentry);
path_put(&path);
return ERR_PTR(err);
err_inode:
@ -1028,20 +1029,14 @@ void free_write_pipe(struct file *f)
struct file *create_read_pipe(struct file *wrf, int flags)
{
struct file *f = get_empty_filp();
/* Grab pipe from the writer */
struct file *f = alloc_file(&wrf->f_path, FMODE_READ,
&read_pipefifo_fops);
if (!f)
return ERR_PTR(-ENFILE);
/* Grab pipe from the writer */
f->f_path = wrf->f_path;
path_get(&wrf->f_path);
f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
f->f_pos = 0;
f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
f->f_op = &read_pipefifo_fops;
f->f_mode = FMODE_READ;
f->f_version = 0;
return f;
}

View file

@ -48,6 +48,7 @@
#include <net/checksum.h>
#include <linux/stat.h>
#include <linux/quotaops.h>
#include <linux/security.h>
#define PRIVROOT_NAME ".reiserfs_priv"
#define XAROOT_NAME "xattrs"
@ -726,15 +727,14 @@ ssize_t
reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
size_t size)
{
struct inode *inode = dentry->d_inode;
struct xattr_handler *handler;
handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
return handler->get(inode, name, buffer, size);
return handler->get(dentry, name, buffer, size, handler->flags);
}
/*
@ -746,15 +746,14 @@ int
reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
struct xattr_handler *handler;
handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
return handler->set(inode, name, value, size, flags);
return handler->set(dentry, name, value, size, flags, handler->flags);
}
/*
@ -764,21 +763,20 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
*/
int reiserfs_removexattr(struct dentry *dentry, const char *name)
{
struct inode *inode = dentry->d_inode;
struct xattr_handler *handler;
handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
}
struct listxattr_buf {
size_t size;
size_t pos;
char *buf;
struct inode *inode;
struct dentry *dentry;
};
static int listxattr_filler(void *buf, const char *name, int namelen,
@ -789,17 +787,19 @@ static int listxattr_filler(void *buf, const char *name, int namelen,
if (name[0] != '.' ||
(namelen != 1 && (name[1] != '.' || namelen != 2))) {
struct xattr_handler *handler;
handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
name);
if (!handler) /* Unsupported xattr name */
return 0;
if (b->buf) {
size = handler->list(b->inode, b->buf + b->pos,
b->size, name, namelen);
size = handler->list(b->dentry, b->buf + b->pos,
b->size, name, namelen,
handler->flags);
if (size > b->size)
return -ERANGE;
} else {
size = handler->list(b->inode, NULL, 0, name, namelen);
size = handler->list(b->dentry, NULL, 0, name,
namelen, handler->flags);
}
b->pos += size;
@ -820,7 +820,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
int err = 0;
loff_t pos = 0;
struct listxattr_buf buf = {
.inode = dentry->d_inode,
.dentry = dentry,
.buf = buffer,
.size = buffer ? size : 0,
};

View file

@ -15,8 +15,10 @@ static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
struct posix_acl *acl);
static int
xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
posix_acl_set(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl;
int error, error2;
struct reiserfs_transaction_handle th;
@ -60,15 +62,16 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
}
static int
xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
size_t size, int type)
{
struct posix_acl *acl;
int error;
if (!reiserfs_posixacl(inode->i_sb))
if (!reiserfs_posixacl(dentry->d_sb))
return -EOPNOTSUPP;
acl = reiserfs_get_acl(inode, type);
acl = reiserfs_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -482,30 +485,12 @@ int reiserfs_acl_chmod(struct inode *inode)
return error;
}
static int
posix_acl_access_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
return -EINVAL;
return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
static int
posix_acl_access_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
return -EINVAL;
return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
static size_t posix_acl_access_list(struct inode *inode, char *list,
static size_t posix_acl_access_list(struct dentry *dentry, char *list,
size_t list_size, const char *name,
size_t name_len)
size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!reiserfs_posixacl(inode->i_sb))
if (!reiserfs_posixacl(dentry->d_sb))
return 0;
if (list && size <= list_size)
memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@ -514,35 +499,18 @@ static size_t posix_acl_access_list(struct inode *inode, char *list,
struct xattr_handler reiserfs_posix_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.get = posix_acl_access_get,
.set = posix_acl_access_set,
.flags = ACL_TYPE_ACCESS,
.get = posix_acl_get,
.set = posix_acl_set,
.list = posix_acl_access_list,
};
static int
posix_acl_default_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
return -EINVAL;
return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
static int
posix_acl_default_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
return -EINVAL;
return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
static size_t posix_acl_default_list(struct inode *inode, char *list,
static size_t posix_acl_default_list(struct dentry *dentry, char *list,
size_t list_size, const char *name,
size_t name_len)
size_t name_len, int type)
{
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!reiserfs_posixacl(inode->i_sb))
if (!reiserfs_posixacl(dentry->d_sb))
return 0;
if (list && size <= list_size)
memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@ -551,7 +519,8 @@ static size_t posix_acl_default_list(struct inode *inode, char *list,
struct xattr_handler reiserfs_posix_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.get = posix_acl_default_get,
.set = posix_acl_default_set,
.flags = ACL_TYPE_DEFAULT,
.get = posix_acl_get,
.set = posix_acl_set,
.list = posix_acl_default_list,
};

View file

@ -8,36 +8,37 @@
#include <asm/uaccess.h>
static int
security_get(struct inode *inode, const char *name, void *buffer, size_t size)
security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
int handler_flags)
{
if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
return -EINVAL;
if (IS_PRIVATE(inode))
if (IS_PRIVATE(dentry->d_inode))
return -EPERM;
return reiserfs_xattr_get(inode, name, buffer, size);
return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
}
static int
security_set(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
security_set(struct dentry *dentry, const char *name, const void *buffer,
size_t size, int flags, int handler_flags)
{
if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
return -EINVAL;
if (IS_PRIVATE(inode))
if (IS_PRIVATE(dentry->d_inode))
return -EPERM;
return reiserfs_xattr_set(inode, name, buffer, size, flags);
return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
}
static size_t security_list(struct inode *inode, char *list, size_t list_len,
const char *name, size_t namelen)
static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
const char *name, size_t namelen, int handler_flags)
{
const size_t len = namelen + 1;
if (IS_PRIVATE(inode))
if (IS_PRIVATE(dentry->d_inode))
return 0;
if (list && len <= list_len) {

View file

@ -8,36 +8,37 @@
#include <asm/uaccess.h>
static int
trusted_get(struct inode *inode, const char *name, void *buffer, size_t size)
trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
int handler_flags)
{
if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
return -EPERM;
return reiserfs_xattr_get(inode, name, buffer, size);
return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
}
static int
trusted_set(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
trusted_set(struct dentry *dentry, const char *name, const void *buffer,
size_t size, int flags, int handler_flags)
{
if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
return -EPERM;
return reiserfs_xattr_set(inode, name, buffer, size, flags);
return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
}
static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int handler_flags)
{
const size_t len = name_len + 1;
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
return 0;
if (list && len <= list_size) {

View file

@ -7,34 +7,35 @@
#include <asm/uaccess.h>
static int
user_get(struct inode *inode, const char *name, void *buffer, size_t size)
user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
int handler_flags)
{
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
if (!reiserfs_xattrs_user(inode->i_sb))
if (!reiserfs_xattrs_user(dentry->d_sb))
return -EOPNOTSUPP;
return reiserfs_xattr_get(inode, name, buffer, size);
return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
}
static int
user_set(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
user_set(struct dentry *dentry, const char *name, const void *buffer,
size_t size, int flags, int handler_flags)
{
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
if (!reiserfs_xattrs_user(inode->i_sb))
if (!reiserfs_xattrs_user(dentry->d_sb))
return -EOPNOTSUPP;
return reiserfs_xattr_set(inode, name, buffer, size, flags);
return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
}
static size_t user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int handler_flags)
{
const size_t len = name_len + 1;
if (!reiserfs_xattrs_user(inode->i_sb))
if (!reiserfs_xattrs_user(dentry->d_sb))
return 0;
if (list && len <= list_size) {
memcpy(list, name, name_len);

View file

@ -615,12 +615,11 @@ ssize_t
generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
return handler->get(inode, name, buffer, size);
return handler->get(dentry, name, buffer, size, handler->flags);
}
/*
@ -630,18 +629,20 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
ssize_t
generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{
struct inode *inode = dentry->d_inode;
struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
unsigned int size = 0;
if (!buffer) {
for_each_xattr_handler(handlers, handler)
size += handler->list(inode, NULL, 0, NULL, 0);
for_each_xattr_handler(handlers, handler) {
size += handler->list(dentry, NULL, 0, NULL, 0,
handler->flags);
}
} else {
char *buf = buffer;
for_each_xattr_handler(handlers, handler) {
size = handler->list(inode, buf, buffer_size, NULL, 0);
size = handler->list(dentry, buf, buffer_size,
NULL, 0, handler->flags);
if (size > buffer_size)
return -ERANGE;
buf += size;
@ -659,14 +660,13 @@ int
generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
if (size == 0)
value = ""; /* empty EA, do not remove */
handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
return handler->set(inode, name, value, size, flags);
return handler->set(dentry, name, value, size, 0, handler->flags);
}
/*
@ -677,12 +677,12 @@ int
generic_removexattr(struct dentry *dentry, const char *name)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
return handler->set(dentry, name, NULL, 0,
XATTR_REPLACE, handler->flags);
}
EXPORT_SYMBOL(generic_getxattr);

View file

@ -354,37 +354,14 @@ xfs_acl_chmod(struct inode *inode)
return error;
}
/*
* System xattr handlers.
*
* Currently Posix ACLs are the only system namespace extended attribute
* handlers supported by XFS, so we just implement the handlers here.
* If we ever support other system extended attributes this will need
* some refactoring.
*/
static int
xfs_decode_acl(const char *name)
{
if (strcmp(name, "posix_acl_access") == 0)
return ACL_TYPE_ACCESS;
else if (strcmp(name, "posix_acl_default") == 0)
return ACL_TYPE_DEFAULT;
return -EINVAL;
}
static int
xfs_xattr_system_get(struct inode *inode, const char *name,
void *value, size_t size)
xfs_xattr_acl_get(struct dentry *dentry, const char *name,
void *value, size_t size, int type)
{
struct posix_acl *acl;
int type, error;
int error;
type = xfs_decode_acl(name);
if (type < 0)
return type;
acl = xfs_get_acl(inode, type);
acl = xfs_get_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
@ -397,15 +374,13 @@ xfs_xattr_system_get(struct inode *inode, const char *name,
}
static int
xfs_xattr_system_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
xfs_xattr_acl_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int type)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl = NULL;
int error = 0, type;
int error = 0;
type = xfs_decode_acl(name);
if (type < 0)
return type;
if (flags & XATTR_CREATE)
return -EINVAL;
if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
@ -462,8 +437,16 @@ xfs_xattr_system_set(struct inode *inode, const char *name,
return error;
}
struct xattr_handler xfs_xattr_system_handler = {
.prefix = XATTR_SYSTEM_PREFIX,
.get = xfs_xattr_system_get,
.set = xfs_xattr_system_set,
struct xattr_handler xfs_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.flags = ACL_TYPE_ACCESS,
.get = xfs_xattr_acl_get,
.set = xfs_xattr_acl_set,
};
struct xattr_handler xfs_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.get = xfs_xattr_acl_get,
.set = xfs_xattr_acl_set,
};

View file

@ -30,10 +30,10 @@
static int
__xfs_xattr_get(struct inode *inode, const char *name,
xfs_xattr_get(struct dentry *dentry, const char *name,
void *value, size_t size, int xflags)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_inode *ip = XFS_I(dentry->d_inode);
int error, asize = size;
if (strcmp(name, "") == 0)
@ -52,10 +52,10 @@ __xfs_xattr_get(struct inode *inode, const char *name,
}
static int
__xfs_xattr_set(struct inode *inode, const char *name, const void *value,
xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags, int xflags)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_inode *ip = XFS_I(dentry->d_inode);
if (strcmp(name, "") == 0)
return -EINVAL;
@ -71,75 +71,34 @@ __xfs_xattr_set(struct inode *inode, const char *name, const void *value,
return -xfs_attr_set(ip, name, (void *)value, size, xflags);
}
static int
xfs_xattr_user_get(struct inode *inode, const char *name,
void *value, size_t size)
{
return __xfs_xattr_get(inode, name, value, size, 0);
}
static int
xfs_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return __xfs_xattr_set(inode, name, value, size, flags, 0);
}
static struct xattr_handler xfs_xattr_user_handler = {
.prefix = XATTR_USER_PREFIX,
.get = xfs_xattr_user_get,
.set = xfs_xattr_user_set,
.flags = 0, /* no flags implies user namespace */
.get = xfs_xattr_get,
.set = xfs_xattr_set,
};
static int
xfs_xattr_trusted_get(struct inode *inode, const char *name,
void *value, size_t size)
{
return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT);
}
static int
xfs_xattr_trusted_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT);
}
static struct xattr_handler xfs_xattr_trusted_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = xfs_xattr_trusted_get,
.set = xfs_xattr_trusted_set,
.flags = ATTR_ROOT,
.get = xfs_xattr_get,
.set = xfs_xattr_set,
};
static int
xfs_xattr_secure_get(struct inode *inode, const char *name,
void *value, size_t size)
{
return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE);
}
static int
xfs_xattr_secure_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE);
}
static struct xattr_handler xfs_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = xfs_xattr_secure_get,
.set = xfs_xattr_secure_set,
.flags = ATTR_SECURE,
.get = xfs_xattr_get,
.set = xfs_xattr_set,
};
struct xattr_handler *xfs_xattr_handlers[] = {
&xfs_xattr_user_handler,
&xfs_xattr_trusted_handler,
&xfs_xattr_security_handler,
#ifdef CONFIG_XFS_POSIX_ACL
&xfs_xattr_system_handler,
&xfs_xattr_acl_access_handler,
&xfs_xattr_acl_default_handler,
#endif
NULL
};

View file

@ -49,7 +49,8 @@ extern int xfs_acl_chmod(struct inode *inode);
extern int posix_acl_access_exists(struct inode *inode);
extern int posix_acl_default_exists(struct inode *inode);
extern struct xattr_handler xfs_xattr_system_handler;
extern struct xattr_handler xfs_xattr_acl_access_handler;
extern struct xattr_handler xfs_xattr_acl_default_handler;
#else
# define xfs_check_acl NULL
# define xfs_get_acl(inode, type) NULL

View file

@ -18,11 +18,9 @@ extern void drop_file_write_access(struct file *file);
struct file_operations;
struct vfsmount;
struct dentry;
extern int init_file(struct file *, struct vfsmount *mnt,
struct dentry *dentry, fmode_t mode,
const struct file_operations *fop);
extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry,
fmode_t mode, const struct file_operations *fop);
struct path;
extern struct file *alloc_file(struct path *, fmode_t mode,
const struct file_operations *fop);
static inline void fput_light(struct file *file, int fput_needed)
{

View file

@ -2189,7 +2189,6 @@ static inline void insert_inode_hash(struct inode *inode) {
__insert_inode_hash(inode, inode->i_ino);
}
extern struct file * get_empty_filp(void);
extern void file_move(struct file *f, struct list_head *list);
extern void file_kill(struct file *f);
#ifdef CONFIG_BLOCK

View file

@ -1,36 +1,15 @@
/*
* include/linux/generic_acl.h
*
* (C) 2005 Andreas Gruenbacher <agruen@suse.de>
*
* This file is released under the GPL.
*/
#ifndef LINUX_GENERIC_ACL_H
#define LINUX_GENERIC_ACL_H
#ifndef GENERIC_ACL_H
#define GENERIC_ACL_H
#include <linux/xattr.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
struct inode;
/**
* struct generic_acl_operations - filesystem operations
*
* Filesystems must make these operations available to the generic
* operations.
*/
struct generic_acl_operations {
struct posix_acl *(*getacl)(struct inode *, int);
void (*setacl)(struct inode *, int, struct posix_acl *);
};
extern struct xattr_handler generic_acl_access_handler;
extern struct xattr_handler generic_acl_default_handler;
size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
char *, size_t);
int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
void *, size_t);
int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
const void *, size_t);
int generic_acl_init(struct inode *, struct inode *,
struct generic_acl_operations *);
int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
int generic_acl_init(struct inode *, struct inode *);
int generic_acl_chmod(struct inode *);
int generic_check_acl(struct inode *inode, int mask);
#endif
#endif /* LINUX_GENERIC_ACL_H */

View file

@ -13,18 +13,14 @@
#include <linux/fs.h>
struct linux_binprm;
#define IMA_COUNT_UPDATE 1
#define IMA_COUNT_LEAVE 0
#ifdef CONFIG_IMA
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_inode_alloc(struct inode *inode);
extern void ima_inode_free(struct inode *inode);
extern int ima_path_check(struct path *path, int mask, int update_counts);
extern int ima_path_check(struct path *path, int mask);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern void ima_counts_get(struct file *file);
extern void ima_counts_put(struct path *path, int mask);
#else
static inline int ima_bprm_check(struct linux_binprm *bprm)
@ -42,7 +38,7 @@ static inline void ima_inode_free(struct inode *inode)
return;
}
static inline int ima_path_check(struct path *path, int mask, int update_counts)
static inline int ima_path_check(struct path *path, int mask)
{
return 0;
}
@ -62,9 +58,5 @@ static inline void ima_counts_get(struct file *file)
return;
}
static inline void ima_counts_put(struct path *path, int mask)
{
return;
}
#endif /* CONFIG_IMA_H */
#endif /* _LINUX_IMA_H */

View file

@ -23,7 +23,6 @@ struct proc_mounts {
struct fs_struct;
extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt);
extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
struct fs_struct *);
extern void put_mnt_ns(struct mnt_namespace *ns);

View file

@ -41,20 +41,4 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
extern int init_tmpfs(void);
extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
#ifdef CONFIG_TMPFS_POSIX_ACL
int shmem_check_acl(struct inode *, int);
int shmem_acl_init(struct inode *, struct inode *);
extern struct xattr_handler shmem_xattr_acl_access_handler;
extern struct xattr_handler shmem_xattr_acl_default_handler;
extern struct generic_acl_operations shmem_acl_ops;
#else
static inline int shmem_acl_init(struct inode *inode, struct inode *dir)
{
return 0;
}
#endif /* CONFIG_TMPFS_POSIX_ACL */
#endif

View file

@ -38,12 +38,13 @@ struct dentry;
struct xattr_handler {
char *prefix;
size_t (*list)(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len);
int (*get)(struct inode *inode, const char *name, void *buffer,
size_t size);
int (*set)(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags);
int flags; /* fs private flags passed back to the handlers */
size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len, int handler_flags);
int (*get)(struct dentry *dentry, const char *name, void *buffer,
size_t size, int handler_flags);
int (*set)(struct dentry *dentry, const char *name, const void *buffer,
size_t size, int flags, int handler_flags);
};
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);

View file

@ -32,7 +32,6 @@
#include <linux/nsproxy.h>
#include <linux/pid.h>
#include <linux/ipc_namespace.h>
#include <linux/ima.h>
#include <net/sock.h>
#include "util.h"
@ -734,7 +733,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
error = PTR_ERR(filp);
goto out_putfd;
}
ima_counts_get(filp);
fd_install(fd, filp);
goto out_upsem;

View file

@ -39,7 +39,6 @@
#include <linux/nsproxy.h>
#include <linux/mount.h>
#include <linux/ipc_namespace.h>
#include <linux/ima.h>
#include <asm/uaccess.h>
@ -879,8 +878,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
if (err)
goto out_unlock;
path.dentry = dget(shp->shm_file->f_path.dentry);
path.mnt = shp->shm_file->f_path.mnt;
path = shp->shm_file->f_path;
path_get(&path);
shp->shm_nattch++;
size = i_size_read(path.dentry->d_inode);
shm_unlock(shp);
@ -890,13 +889,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
if (!sfd)
goto out_put_dentry;
file = alloc_file(path.mnt, path.dentry, f_mode,
is_file_hugepages(shp->shm_file) ?
file = alloc_file(&path, f_mode,
is_file_hugepages(shp->shm_file) ?
&shm_file_operations_huge :
&shm_file_operations);
if (!file)
goto out_free;
ima_counts_get(file);
file->private_data = sfd;
file->f_mapping = shp->shm_file->f_mapping;
@ -951,7 +949,7 @@ out_unlock:
out_free:
kfree(sfd);
out_put_dentry:
dput(path.dentry);
path_put(&path);
goto out_nattch;
}

View file

@ -22,7 +22,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlb.o
obj-$(CONFIG_NUMA) += mempolicy.o
obj-$(CONFIG_SPARSEMEM) += sparse.o
obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
obj-$(CONFIG_SLOB) += slob.o
obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
obj-$(CONFIG_KSM) += ksm.o

View file

@ -2240,7 +2240,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
size_t count, ssize_t written)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
ssize_t status;
struct iov_iter i;
@ -2252,15 +2251,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
*ppos = pos + status;
}
/*
* If we get here for O_DIRECT writes then we must have fallen through
* to buffered writes (block instantiation inside i_size). So we sync
* the file data here, to try to honour O_DIRECT expectations.
*/
if (unlikely(file->f_flags & O_DIRECT) && written)
status = filemap_write_and_wait_range(mapping,
pos, pos + written - 1);
return written ? written : status;
}
EXPORT_SYMBOL(generic_file_buffered_write);
@ -2359,10 +2349,7 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
* semantics.
*/
endbyte = pos + written_buffered - written - 1;
err = do_sync_mapping_range(file->f_mapping, pos, endbyte,
SYNC_FILE_RANGE_WAIT_BEFORE|
SYNC_FILE_RANGE_WRITE|
SYNC_FILE_RANGE_WAIT_AFTER);
err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
if (err == 0) {
written = written_buffered;
invalidate_mapping_pages(mapping,

View file

@ -29,7 +29,6 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/swap.h>
#include <linux/ima.h>
static struct vfsmount *shm_mnt;
@ -42,6 +41,7 @@ static struct vfsmount *shm_mnt;
#include <linux/xattr.h>
#include <linux/exportfs.h>
#include <linux/posix_acl.h>
#include <linux/generic_acl.h>
#include <linux/mman.h>
#include <linux/string.h>
@ -810,7 +810,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
error = inode_setattr(inode, attr);
#ifdef CONFIG_TMPFS_POSIX_ACL
if (!error && (attr->ia_valid & ATTR_MODE))
error = generic_acl_chmod(inode, &shmem_acl_ops);
error = generic_acl_chmod(inode);
#endif
if (page)
page_cache_release(page);
@ -1824,11 +1824,13 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
return error;
}
}
error = shmem_acl_init(inode, dir);
#ifdef CONFIG_TMPFS_POSIX_ACL
error = generic_acl_init(inode, dir);
if (error) {
iput(inode);
return error;
}
#endif
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
@ -2043,27 +2045,28 @@ static const struct inode_operations shmem_symlink_inode_operations = {
* filesystem level, though.
*/
static size_t shmem_xattr_security_list(struct inode *inode, char *list,
static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
size_t list_len, const char *name,
size_t name_len)
size_t name_len, int handler_flags)
{
return security_inode_listsecurity(inode, list, list_len);
return security_inode_listsecurity(dentry->d_inode, list, list_len);
}
static int shmem_xattr_security_get(struct inode *inode, const char *name,
void *buffer, size_t size)
static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int handler_flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return xattr_getsecurity(inode, name, buffer, size);
return xattr_getsecurity(dentry->d_inode, name, buffer, size);
}
static int shmem_xattr_security_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags, int handler_flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return security_inode_setsecurity(inode, name, value, size, flags);
return security_inode_setsecurity(dentry->d_inode, name, value,
size, flags);
}
static struct xattr_handler shmem_xattr_security_handler = {
@ -2074,8 +2077,8 @@ static struct xattr_handler shmem_xattr_security_handler = {
};
static struct xattr_handler *shmem_xattr_handlers[] = {
&shmem_xattr_acl_access_handler,
&shmem_xattr_acl_default_handler,
&generic_acl_access_handler,
&generic_acl_default_handler,
&shmem_xattr_security_handler,
NULL
};
@ -2454,7 +2457,7 @@ static const struct inode_operations shmem_inode_operations = {
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
.check_acl = shmem_check_acl,
.check_acl = generic_check_acl,
#endif
};
@ -2477,7 +2480,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
.check_acl = shmem_check_acl,
.check_acl = generic_check_acl,
#endif
};
@ -2488,7 +2491,7 @@ static const struct inode_operations shmem_special_inode_operations = {
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
.check_acl = shmem_check_acl,
.check_acl = generic_check_acl,
#endif
};
@ -2626,7 +2629,8 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
int error;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct path path;
struct dentry *root;
struct qstr this;
if (IS_ERR(shm_mnt))
@ -2643,38 +2647,35 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
this.len = strlen(name);
this.hash = 0; /* will go */
root = shm_mnt->mnt_root;
dentry = d_alloc(root, &this);
if (!dentry)
path.dentry = d_alloc(root, &this);
if (!path.dentry)
goto put_memory;
error = -ENFILE;
file = get_empty_filp();
if (!file)
goto put_dentry;
path.mnt = mntget(shm_mnt);
error = -ENOSPC;
inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags);
if (!inode)
goto close_file;
goto put_dentry;
d_instantiate(dentry, inode);
d_instantiate(path.dentry, inode);
inode->i_size = size;
inode->i_nlink = 0; /* It is unlinked */
init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
&shmem_file_operations);
#ifndef CONFIG_MMU
error = ramfs_nommu_expand_for_mapping(inode, size);
if (error)
goto close_file;
goto put_dentry;
#endif
ima_counts_get(file);
error = -ENFILE;
file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
&shmem_file_operations);
if (!file)
goto put_dentry;
return file;
close_file:
put_filp(file);
put_dentry:
dput(dentry);
path_put(&path);
put_memory:
shmem_unacct_size(flags, size);
return ERR_PTR(error);

View file

@ -1,171 +0,0 @@
/*
* mm/shmem_acl.c
*
* (C) 2005 Andreas Gruenbacher <agruen@suse.de>
*
* This file is released under the GPL.
*/
#include <linux/fs.h>
#include <linux/shmem_fs.h>
#include <linux/xattr.h>
#include <linux/generic_acl.h>
/**
* shmem_get_acl - generic_acl_operations->getacl() operation
*/
static struct posix_acl *
shmem_get_acl(struct inode *inode, int type)
{
struct posix_acl *acl = NULL;
spin_lock(&inode->i_lock);
switch(type) {
case ACL_TYPE_ACCESS:
acl = posix_acl_dup(inode->i_acl);
break;
case ACL_TYPE_DEFAULT:
acl = posix_acl_dup(inode->i_default_acl);
break;
}
spin_unlock(&inode->i_lock);
return acl;
}
/**
* shmem_set_acl - generic_acl_operations->setacl() operation
*/
static void
shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
{
struct posix_acl *free = NULL;
spin_lock(&inode->i_lock);
switch(type) {
case ACL_TYPE_ACCESS:
free = inode->i_acl;
inode->i_acl = posix_acl_dup(acl);
break;
case ACL_TYPE_DEFAULT:
free = inode->i_default_acl;
inode->i_default_acl = posix_acl_dup(acl);
break;
}
spin_unlock(&inode->i_lock);
posix_acl_release(free);
}
struct generic_acl_operations shmem_acl_ops = {
.getacl = shmem_get_acl,
.setacl = shmem_set_acl,
};
/**
* shmem_list_acl_access, shmem_get_acl_access, shmem_set_acl_access,
* shmem_xattr_acl_access_handler - plumbing code to implement the
* system.posix_acl_access xattr using the generic acl functions.
*/
static size_t
shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
list, list_size);
}
static int
shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
size);
}
static int
shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
size);
}
struct xattr_handler shmem_xattr_acl_access_handler = {
.prefix = POSIX_ACL_XATTR_ACCESS,
.list = shmem_list_acl_access,
.get = shmem_get_acl_access,
.set = shmem_set_acl_access,
};
/**
* shmem_list_acl_default, shmem_get_acl_default, shmem_set_acl_default,
* shmem_xattr_acl_default_handler - plumbing code to implement the
* system.posix_acl_default xattr using the generic acl functions.
*/
static size_t
shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
list, list_size);
}
static int
shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
size_t size)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
size);
}
static int
shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
size_t size, int flags)
{
if (strcmp(name, "") != 0)
return -EINVAL;
return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
size);
}
struct xattr_handler shmem_xattr_acl_default_handler = {
.prefix = POSIX_ACL_XATTR_DEFAULT,
.list = shmem_list_acl_default,
.get = shmem_get_acl_default,
.set = shmem_set_acl_default,
};
/**
* shmem_acl_init - Inizialize the acl(s) of a new inode
*/
int
shmem_acl_init(struct inode *inode, struct inode *dir)
{
return generic_acl_init(inode, dir, &shmem_acl_ops);
}
/**
* shmem_check_acl - check_acl() callback for generic_permission()
*/
int
shmem_check_acl(struct inode *inode, int mask)
{
struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
if (acl) {
int error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
return error;
}
return -EAGAIN;
}

View file

@ -42,6 +42,8 @@
#include <net/9p/client.h>
#include <net/9p/transport.h>
#include <linux/syscalls.h> /* killme */
#define P9_PORT 564
#define MAX_SOCK_BUF (64*1024)
#define MAXPOLLWADDR 2
@ -788,24 +790,41 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
static int p9_socket_open(struct p9_client *client, struct socket *csocket)
{
int fd, ret;
struct p9_trans_fd *p;
int ret, fd;
p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
if (!p)
return -ENOMEM;
csocket->sk->sk_allocation = GFP_NOIO;
fd = sock_map_fd(csocket, 0);
if (fd < 0) {
P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
sock_release(csocket);
kfree(p);
return fd;
}
ret = p9_fd_open(client, fd, fd);
if (ret < 0) {
P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
get_file(csocket->file);
get_file(csocket->file);
p->wr = p->rd = csocket->file;
client->trans = p;
client->status = Connected;
sys_close(fd); /* still racy */
p->rd->f_flags |= O_NONBLOCK;
p->conn = p9_conn_create(client);
if (IS_ERR(p->conn)) {
ret = PTR_ERR(p->conn);
p->conn = NULL;
kfree(p);
sockfd_put(csocket);
sockfd_put(csocket);
return ret;
}
((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK;
return 0;
}
@ -883,7 +902,6 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
struct socket *csocket;
struct sockaddr_in sin_server;
struct p9_fd_opts opts;
struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
err = parse_opts(args, &opts);
if (err < 0)
@ -897,12 +915,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
sin_server.sin_family = AF_INET;
sin_server.sin_addr.s_addr = in_aton(addr);
sin_server.sin_port = htons(opts.port);
sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
if (!csocket) {
if (err) {
P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
err = -EIO;
goto error;
return err;
}
err = csocket->ops->connect(csocket,
@ -912,30 +929,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
P9_EPRINTK(KERN_ERR,
"p9_trans_tcp: problem connecting socket to %s\n",
addr);
goto error;
}
err = p9_socket_open(client, csocket);
if (err < 0)
goto error;
p = (struct p9_trans_fd *) client->trans;
p->conn = p9_conn_create(client);
if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn);
p->conn = NULL;
goto error;
}
return 0;
error:
if (csocket)
sock_release(csocket);
return err;
}
kfree(p);
return err;
return p9_socket_open(client, csocket);
}
static int
@ -944,49 +942,33 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
int err;
struct socket *csocket;
struct sockaddr_un sun_server;
struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
csocket = NULL;
if (strlen(addr) > UNIX_PATH_MAX) {
P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
addr);
err = -ENAMETOOLONG;
goto error;
return -ENAMETOOLONG;
}
sun_server.sun_family = PF_UNIX;
strcpy(sun_server.sun_path, addr);
sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
err = sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
if (err < 0) {
P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem creating socket\n");
return err;
}
err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
sizeof(struct sockaddr_un) - 1, 0);
if (err < 0) {
P9_EPRINTK(KERN_ERR,
"p9_trans_unix: problem connecting socket: %s: %d\n",
addr, err);
goto error;
}
err = p9_socket_open(client, csocket);
if (err < 0)
goto error;
p = (struct p9_trans_fd *) client->trans;
p->conn = p9_conn_create(client);
if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn);
p->conn = NULL;
goto error;
}
return 0;
error:
if (csocket)
sock_release(csocket);
return err;
}
kfree(p);
return err;
return p9_socket_open(client, csocket);
}
static int
@ -994,7 +976,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
{
int err;
struct p9_fd_opts opts;
struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
struct p9_trans_fd *p;
parse_opts(args, &opts);
@ -1005,21 +987,19 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
err = p9_fd_open(client, opts.rfd, opts.wfd);
if (err < 0)
goto error;
return err;
p = (struct p9_trans_fd *) client->trans;
p->conn = p9_conn_create(client);
if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn);
p->conn = NULL;
goto error;
fput(p->rd);
fput(p->wr);
return err;
}
return 0;
error:
kfree(p);
return err;
}
static struct p9_trans_module p9_tcp_trans = {

View file

@ -355,68 +355,61 @@ static const struct dentry_operations sockfs_dentry_operations = {
* but we take care of internal coherence yet.
*/
static int sock_alloc_fd(struct file **filep, int flags)
static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
{
struct qstr name = { .name = "" };
struct path path;
struct file *file;
int fd;
fd = get_unused_fd_flags(flags);
if (likely(fd >= 0)) {
struct file *file = get_empty_filp();
if (unlikely(fd < 0))
return fd;
*filep = file;
if (unlikely(!file)) {
put_unused_fd(fd);
return -ENFILE;
}
} else
*filep = NULL;
return fd;
}
static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
{
struct dentry *dentry;
struct qstr name = { .name = "" };
dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
if (unlikely(!dentry))
path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
if (unlikely(!path.dentry)) {
put_unused_fd(fd);
return -ENOMEM;
}
path.mnt = mntget(sock_mnt);
dentry->d_op = &sockfs_dentry_operations;
path.dentry->d_op = &sockfs_dentry_operations;
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(dentry, SOCK_INODE(sock));
path.dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(path.dentry, SOCK_INODE(sock));
SOCK_INODE(sock)->i_fop = &socket_file_ops;
file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
&socket_file_ops);
if (unlikely(!file)) {
/* drop dentry, keep inode */
atomic_inc(&path.dentry->d_inode->i_count);
path_put(&path);
put_unused_fd(fd);
return -ENFILE;
}
sock->file = file;
init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
&socket_file_ops);
SOCK_INODE(sock)->i_fop = &socket_file_ops;
file->f_flags = O_RDWR | (flags & O_NONBLOCK);
file->f_pos = 0;
file->private_data = sock;
return 0;
*f = file;
return fd;
}
int sock_map_fd(struct socket *sock, int flags)
{
struct file *newfile;
int fd = sock_alloc_fd(&newfile, flags);
int fd = sock_alloc_file(sock, &newfile, flags);
if (likely(fd >= 0)) {
int err = sock_attach_fd(sock, newfile, flags);
if (unlikely(err < 0)) {
put_filp(newfile);
put_unused_fd(fd);
return err;
}
if (likely(fd >= 0))
fd_install(fd, newfile);
}
return fd;
}
@ -1390,29 +1383,19 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
if (err < 0)
goto out_release_both;
fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
fd1 = sock_alloc_file(sock1, &newfile1, flags);
if (unlikely(fd1 < 0)) {
err = fd1;
goto out_release_both;
}
fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
fd2 = sock_alloc_file(sock2, &newfile2, flags);
if (unlikely(fd2 < 0)) {
err = fd2;
put_filp(newfile1);
put_unused_fd(fd1);
goto out_release_both;
}
err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
goto out_fd2;
}
err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
fput(newfile1);
goto out_fd1;
put_unused_fd(fd1);
sock_release(sock2);
goto out;
}
audit_fd_pair(fd1, fd2);
@ -1438,16 +1421,6 @@ out_release_1:
sock_release(sock1);
out:
return err;
out_fd2:
put_filp(newfile1);
sock_release(sock1);
out_fd1:
put_filp(newfile2);
sock_release(sock2);
put_unused_fd(fd1);
put_unused_fd(fd2);
goto out;
}
/*
@ -1551,17 +1524,13 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
*/
__module_get(newsock->ops->owner);
newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
newfd = sock_alloc_file(newsock, &newfile, flags);
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
goto out_put;
}
err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
if (err < 0)
goto out_fd_simple;
err = security_socket_accept(sock, newsock);
if (err)
goto out_fd;
@ -1591,11 +1560,6 @@ out_put:
fput_light(sock->file, fput_needed);
out:
return err;
out_fd_simple:
sock_release(newsock);
put_filp(newfile);
put_unused_fd(newfd);
goto out_put;
out_fd:
fput(newfile);
put_unused_fd(newfd);

View file

@ -97,7 +97,6 @@ static inline unsigned long ima_hash_key(u8 *digest)
/* iint cache flags */
#define IMA_MEASURED 1
#define IMA_IINT_DUMP_STACK 512
/* integrity data associated with an inode */
struct ima_iint_cache {
@ -128,8 +127,6 @@ void ima_template_show(struct seq_file *m, void *e,
*/
struct ima_iint_cache *ima_iint_insert(struct inode *inode);
struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
void ima_iint_delete(struct inode *inode);
void iint_free(struct kref *kref);
void iint_rcu_free(struct rcu_head *rcu);

View file

@ -19,8 +19,6 @@
#include <linux/radix-tree.h>
#include "ima.h"
#define ima_iint_delete ima_inode_free
RADIX_TREE(ima_iint_store, GFP_ATOMIC);
DEFINE_SPINLOCK(ima_iint_lock);
@ -45,22 +43,21 @@ out:
return iint;
}
/* Allocate memory for the iint associated with the inode
* from the iint_cache slab, initialize the iint, and
* insert it into the radix tree.
*
* On success return a pointer to the iint; on failure return NULL.
/**
* ima_inode_alloc - allocate an iint associated with an inode
* @inode: pointer to the inode
*/
struct ima_iint_cache *ima_iint_insert(struct inode *inode)
int ima_inode_alloc(struct inode *inode)
{
struct ima_iint_cache *iint = NULL;
int rc = 0;
if (!ima_initialized)
return iint;
return 0;
iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
if (!iint)
return iint;
return -ENOMEM;
rc = radix_tree_preload(GFP_NOFS);
if (rc < 0)
@ -70,66 +67,14 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode)
rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
spin_unlock(&ima_iint_lock);
out:
if (rc < 0) {
if (rc < 0)
kmem_cache_free(iint_cache, iint);
if (rc == -EEXIST) {
spin_lock(&ima_iint_lock);
iint = radix_tree_lookup(&ima_iint_store,
(unsigned long)inode);
spin_unlock(&ima_iint_lock);
} else
iint = NULL;
}
radix_tree_preload_end();
return iint;
return rc;
}
/**
* ima_inode_alloc - allocate an iint associated with an inode
* @inode: pointer to the inode
*
* Return 0 on success, 1 on failure.
*/
int ima_inode_alloc(struct inode *inode)
{
struct ima_iint_cache *iint;
if (!ima_initialized)
return 0;
iint = ima_iint_insert(inode);
if (!iint)
return 1;
return 0;
}
/* ima_iint_find_insert_get - get the iint associated with an inode
*
* Most insertions are done at inode_alloc, except those allocated
* before late_initcall. When the iint does not exist, allocate it,
* initialize and insert it, and increment the iint refcount.
*
* (Can't initialize at security_initcall before any inodes are
* allocated, got to wait at least until proc_init.)
*
* Return the iint.
*/
struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
{
struct ima_iint_cache *iint = NULL;
iint = ima_iint_find_get(inode);
if (iint)
return iint;
iint = ima_iint_insert(inode);
if (iint)
kref_get(&iint->refcount);
return iint;
}
EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
/* iint_free - called when the iint refcount goes to zero */
void iint_free(struct kref *kref)
{
@ -164,12 +109,12 @@ void iint_rcu_free(struct rcu_head *rcu_head)
}
/**
* ima_iint_delete - called on integrity_inode_free
* ima_inode_free - called on security_inode_free
* @inode: pointer to the inode
*
* Free the integrity information(iint) associated with an inode.
*/
void ima_iint_delete(struct inode *inode)
void ima_inode_free(struct inode *inode)
{
struct ima_iint_cache *iint;

View file

@ -13,8 +13,8 @@
* License.
*
* File: ima_main.c
* implements the IMA hooks: ima_bprm_check, ima_file_mmap,
* and ima_path_check.
* implements the IMA hooks: ima_bprm_check, ima_file_mmap,
* and ima_path_check.
*/
#include <linux/module.h>
#include <linux/file.h>
@ -35,6 +35,100 @@ static int __init hash_setup(char *str)
}
__setup("ima_hash=", hash_setup);
struct ima_imbalance {
struct hlist_node node;
unsigned long fsmagic;
};
/*
* ima_limit_imbalance - emit one imbalance message per filesystem type
*
* Maintain list of filesystem types that do not measure files properly.
* Return false if unknown, true if known.
*/
static bool ima_limit_imbalance(struct file *file)
{
static DEFINE_SPINLOCK(ima_imbalance_lock);
static HLIST_HEAD(ima_imbalance_list);
struct super_block *sb = file->f_dentry->d_sb;
struct ima_imbalance *entry;
struct hlist_node *node;
bool found = false;
rcu_read_lock();
hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
if (entry->fsmagic == sb->s_magic) {
found = true;
break;
}
}
rcu_read_unlock();
if (found)
goto out;
entry = kmalloc(sizeof(*entry), GFP_NOFS);
if (!entry)
goto out;
entry->fsmagic = sb->s_magic;
spin_lock(&ima_imbalance_lock);
/*
* we could have raced and something else might have added this fs
* to the list, but we don't really care
*/
hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
spin_unlock(&ima_imbalance_lock);
printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
entry->fsmagic);
out:
return found;
}
/*
* Update the counts given an fmode_t
*/
static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
{
BUG_ON(!mutex_is_locked(&iint->mutex));
iint->opencount++;
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount++;
if (mode & FMODE_WRITE)
iint->writecount++;
}
/*
* Decrement ima counts
*/
static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
struct file *file)
{
mode_t mode = file->f_mode;
BUG_ON(!mutex_is_locked(&iint->mutex));
iint->opencount--;
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount--;
if (mode & FMODE_WRITE) {
iint->writecount--;
if (iint->writecount == 0) {
if (iint->version != inode->i_version)
iint->flags &= ~IMA_MEASURED;
}
}
if (((iint->opencount < 0) ||
(iint->readcount < 0) ||
(iint->writecount < 0)) &&
!ima_limit_imbalance(file)) {
printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
__FUNCTION__, iint->readcount, iint->writecount,
iint->opencount);
dump_stack();
}
}
/**
* ima_file_free - called on __fput()
* @file: pointer to file structure being freed
@ -54,29 +148,7 @@ void ima_file_free(struct file *file)
return;
mutex_lock(&iint->mutex);
if (iint->opencount <= 0) {
printk(KERN_INFO
"%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
__FUNCTION__, file->f_dentry->d_name.name,
iint->readcount, iint->writecount,
iint->opencount, atomic_long_read(&file->f_count));
if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
dump_stack();
iint->flags |= IMA_IINT_DUMP_STACK;
}
}
iint->opencount--;
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount--;
if (file->f_mode & FMODE_WRITE) {
iint->writecount--;
if (iint->writecount == 0) {
if (iint->version != inode->i_version)
iint->flags &= ~IMA_MEASURED;
}
}
ima_dec_counts(iint, inode, file);
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);
}
@ -116,8 +188,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
{
int rc = 0;
iint->opencount++;
iint->readcount++;
ima_inc_counts(iint, file->f_mode);
rc = ima_collect_measurement(iint, file);
if (!rc)
@ -125,15 +196,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
return rc;
}
static void ima_update_counts(struct ima_iint_cache *iint, int mask)
{
iint->opencount++;
if ((mask & MAY_WRITE) || (mask == 0))
iint->writecount++;
else if (mask & (MAY_READ | MAY_EXEC))
iint->readcount++;
}
/**
* ima_path_check - based on policy, collect/store measurement.
* @path: contains a pointer to the path to be measured
@ -152,7 +214,7 @@ static void ima_update_counts(struct ima_iint_cache *iint, int mask)
* Always return 0 and audit dentry_open failures.
* (Return code will be based upon measurement appraisal.)
*/
int ima_path_check(struct path *path, int mask, int update_counts)
int ima_path_check(struct path *path, int mask)
{
struct inode *inode = path->dentry->d_inode;
struct ima_iint_cache *iint;
@ -161,13 +223,11 @@ int ima_path_check(struct path *path, int mask, int update_counts)
if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;
iint = ima_iint_find_insert_get(inode);
iint = ima_iint_find_get(inode);
if (!iint)
return 0;
mutex_lock(&iint->mutex);
if (update_counts)
ima_update_counts(iint, mask);
rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
if (rc < 0)
@ -219,7 +279,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;
iint = ima_iint_find_insert_get(inode);
iint = ima_iint_find_get(inode);
if (!iint)
return -ENOMEM;
@ -237,39 +297,6 @@ out:
return rc;
}
/*
* ima_counts_put - decrement file counts
*
* File counts are incremented in ima_path_check. On file open
* error, such as ETXTBSY, decrement the counts to prevent
* unnecessary imbalance messages.
*/
void ima_counts_put(struct path *path, int mask)
{
struct inode *inode = path->dentry->d_inode;
struct ima_iint_cache *iint;
/* The inode may already have been freed, freeing the iint
* with it. Verify the inode is not NULL before dereferencing
* it.
*/
if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
return;
iint = ima_iint_find_insert_get(inode);
if (!iint)
return;
mutex_lock(&iint->mutex);
iint->opencount--;
if ((mask & MAY_WRITE) || (mask == 0))
iint->writecount--;
else if (mask & (MAY_READ | MAY_EXEC))
iint->readcount--;
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);
}
/*
* ima_counts_get - increment file counts
*
@ -286,16 +313,11 @@ void ima_counts_get(struct file *file)
if (!ima_initialized || !S_ISREG(inode->i_mode))
return;
iint = ima_iint_find_insert_get(inode);
iint = ima_iint_find_get(inode);
if (!iint)
return;
mutex_lock(&iint->mutex);
iint->opencount++;
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount++;
if (file->f_mode & FMODE_WRITE)
iint->writecount++;
ima_inc_counts(iint, file->f_mode);
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);