Release 4.15 fs/ext4/acl.c
// SPDX-License-Identifier: GPL-2.0
/*
* linux/fs/ext4/acl.c
*
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
#include <linux/quotaops.h>
#include "ext4_jbd2.h"
#include "ext4.h"
#include "xattr.h"
#include "acl.h"
/*
* Convert from filesystem to in-memory representation.
*/
static struct posix_acl *
ext4_acl_from_disk(const void *value, size_t size)
{
const char *end = (char *)value + size;
int n, count;
struct posix_acl *acl;
if (!value)
return NULL;
if (size < sizeof(ext4_acl_header))
return ERR_PTR(-EINVAL);
if (((ext4_acl_header *)value)->a_version !=
cpu_to_le32(EXT4_ACL_VERSION))
return ERR_PTR(-EINVAL);
value = (char *)value + sizeof(ext4_acl_header);
count = ext4_acl_count(size);
if (count < 0)
return ERR_PTR(-EINVAL);
if (count == 0)
return NULL;
acl = posix_acl_alloc(count, GFP_NOFS);
if (!acl)
return ERR_PTR(-ENOMEM);
for (n = 0; n < count; n++) {
ext4_acl_entry *entry =
(ext4_acl_entry *)value;
if ((char *)value + sizeof(ext4_acl_entry_short) > end)
goto fail;
acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
switch (acl->a_entries[n].e_tag) {
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
value = (char *)value +
sizeof(ext4_acl_entry_short);
break;
case ACL_USER:
value = (char *)value + sizeof(ext4_acl_entry);
if ((char *)value > end)
goto fail;
acl->a_entries[n].e_uid =
make_kuid(&init_user_ns,
le32_to_cpu(entry->e_id));
break;
case ACL_GROUP:
value = (char *)value + sizeof(ext4_acl_entry);
if ((char *)value > end)
goto fail;
acl->a_entries[n].e_gid =
make_kgid(&init_user_ns,
le32_to_cpu(entry->e_id));
break;
default:
goto fail;
}
}
if (value != end)
goto fail;
return acl;
fail:
posix_acl_release(acl);
return ERR_PTR(-EINVAL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Kleikamp | 336 | 84.42% | 1 | 25.00% |
Eric W. Biedermann | 50 | 12.56% | 1 | 25.00% |
Mingming Cao | 11 | 2.76% | 1 | 25.00% |
Josef Bacik | 1 | 0.25% | 1 | 25.00% |
Total | 398 | 100.00% | 4 | 100.00% |
/*
* Convert from in-memory to filesystem representation.
*/
static void *
ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
{
ext4_acl_header *ext_acl;
char *e;
size_t n;
*size = ext4_acl_size(acl->a_count);
ext_acl = kmalloc(sizeof(ext4_acl_header) + acl->a_count *
sizeof(ext4_acl_entry), GFP_NOFS);
if (!ext_acl)
return ERR_PTR(-ENOMEM);
ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION);
e = (char *)ext_acl + sizeof(ext4_acl_header);
for (n = 0; n < acl->a_count; n++) {
const struct posix_acl_entry *acl_e = &acl->a_entries[n];
ext4_acl_entry *entry = (ext4_acl_entry *)e;
entry->e_tag = cpu_to_le16(acl_e->e_tag);
entry->e_perm = cpu_to_le16(acl_e->e_perm);
switch (acl_e->e_tag) {
case ACL_USER:
entry->e_id = cpu_to_le32(
from_kuid(&init_user_ns, acl_e->e_uid));
e += sizeof(ext4_acl_entry);
break;
case ACL_GROUP:
entry->e_id = cpu_to_le32(
from_kgid(&init_user_ns, acl_e->e_gid));
e += sizeof(ext4_acl_entry);
break;
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
e += sizeof(ext4_acl_entry_short);
break;
default:
goto fail;
}
}
return (char *)ext_acl;
fail:
kfree(ext_acl);
return ERR_PTR(-EINVAL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Kleikamp | 203 | 76.60% | 1 | 25.00% |
Eric W. Biedermann | 50 | 18.87% | 1 | 25.00% |
Mingming Cao | 11 | 4.15% | 1 | 25.00% |
Josef Bacik | 1 | 0.38% | 1 | 25.00% |
Total | 265 | 100.00% | 4 | 100.00% |
/*
* Inode operation get_posix_acl().
*
* inode->i_mutex: don't care
*/
struct posix_acl *
ext4_get_acl(struct inode *inode, int type)
{
int name_index;
char *value = NULL;
struct posix_acl *acl;
int retval;
switch (type) {
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
BUG();
}
retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
if (retval > 0) {
value = kmalloc(retval, GFP_NOFS);
if (!value)
return ERR_PTR(-ENOMEM);
retval = ext4_xattr_get(inode, name_index, "", value, retval);
}
if (retval > 0)
acl = ext4_acl_from_disk(value, retval);
else if (retval == -ENODATA || retval == -ENOSYS)
acl = NULL;
else
acl = ERR_PTR(retval);
kfree(value);
return acl;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Kleikamp | 147 | 89.09% | 1 | 25.00% |
Al Viro | 11 | 6.67% | 1 | 25.00% |
Mingming Cao | 6 | 3.64% | 1 | 25.00% |
Josef Bacik | 1 | 0.61% | 1 | 25.00% |
Total | 165 | 100.00% | 4 | 100.00% |
/*
* Set the access or default ACL of an inode.
*
* inode->i_mutex: down unless called from ext4_new_inode
*/
static int
__ext4_set_acl(handle_t *handle, struct inode *inode, int type,
struct posix_acl *acl, int xattr_flags)
{
int name_index;
void *value = NULL;
size_t size = 0;
int error;
switch (type) {
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
break;
default:
return -EINVAL;
}
if (acl) {
value = ext4_acl_to_disk(acl, &size);
if (IS_ERR(value))
return (int)PTR_ERR(value);
}
error = ext4_xattr_set_handle(handle, inode, name_index, "",
value, size, xattr_flags);
kfree(value);
if (!error) {
set_cached_acl(inode, type, acl);
}
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Kleikamp | 150 | 92.02% | 1 | 16.67% |
Mingming Cao | 4 | 2.45% | 1 | 16.67% |
Tahsin Erdogan | 4 | 2.45% | 1 | 16.67% |
Al Viro | 2 | 1.23% | 1 | 16.67% |
Ernesto A. Fernández | 2 | 1.23% | 1 | 16.67% |
Christoph Hellwig | 1 | 0.61% | 1 | 16.67% |
Total | 163 | 100.00% | 6 | 100.00% |
int
ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
handle_t *handle;
int error, credits, retries = 0;
size_t acl_size = acl ? ext4_acl_size(acl->a_count) : 0;
umode_t mode = inode->i_mode;
int update_mode = 0;
error = dquot_initialize(inode);
if (error)
return error;
retry:
error = ext4_xattr_set_credits(inode, acl_size, false /* is_create */,
&credits);
if (error)
return error;
handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
if (IS_ERR(handle))
return PTR_ERR(handle);
if ((type == ACL_TYPE_ACCESS) && acl) {
error = posix_acl_update_mode(inode, &mode, &acl);
if (error)
goto out_stop;
update_mode = 1;
}
error = __ext4_set_acl(handle, inode, type, acl, 0 /* xattr_flags */);
if (!error && update_mode) {
inode->i_mode = mode;
inode->i_ctime = current_time(inode);
ext4_mark_inode_dirty(handle, inode);
}
out_stop:
ext4_journal_stop(handle);
if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jan Kara | 81 | 34.91% | 1 | 14.29% |
Tahsin Erdogan | 56 | 24.14% | 4 | 57.14% |
Christoph Hellwig | 49 | 21.12% | 1 | 14.29% |
Dave Kleikamp | 46 | 19.83% | 1 | 14.29% |
Total | 232 | 100.00% | 7 | 100.00% |
/*
* Initialize the ACLs of a new inode. Called from ext4_new_inode.
*
* dir->i_mutex: down
* inode->i_mutex: up (access to inode is still exclusive)
*/
int
ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
{
struct posix_acl *default_acl, *acl;
int error;
error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
if (error)
return error;
if (default_acl) {
error = __ext4_set_acl(handle, inode, ACL_TYPE_DEFAULT,
default_acl, XATTR_CREATE);
posix_acl_release(default_acl);
}
if (acl) {
if (!error)
error = __ext4_set_acl(handle, inode, ACL_TYPE_ACCESS,
acl, XATTR_CREATE);
posix_acl_release(acl);
}
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 60 | 52.17% | 1 | 20.00% |
Dave Kleikamp | 48 | 41.74% | 1 | 20.00% |
Tahsin Erdogan | 4 | 3.48% | 1 | 20.00% |
Al Viro | 3 | 2.61% | 2 | 40.00% |
Total | 115 | 100.00% | 5 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Kleikamp | 943 | 69.34% | 1 | 6.25% |
Christoph Hellwig | 113 | 8.31% | 2 | 12.50% |
Eric W. Biedermann | 100 | 7.35% | 1 | 6.25% |
Jan Kara | 81 | 5.96% | 1 | 6.25% |
Tahsin Erdogan | 67 | 4.93% | 4 | 25.00% |
Mingming Cao | 34 | 2.50% | 1 | 6.25% |
Al Viro | 16 | 1.18% | 3 | 18.75% |
Josef Bacik | 3 | 0.22% | 1 | 6.25% |
Ernesto A. Fernández | 2 | 0.15% | 1 | 6.25% |
Greg Kroah-Hartman | 1 | 0.07% | 1 | 6.25% |
Total | 1360 | 100.00% | 16 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.