Blame view
fs/generic_acl.c
4.7 KB
f0c8bd164 [PATCH] Generic i... |
1 |
/* |
f0c8bd164 [PATCH] Generic i... |
2 3 4 |
* (C) 2005 Andreas Gruenbacher <agruen@suse.de> * * This file is released under the GPL. |
1c7c474c3 make generic_acl ... |
5 6 |
* * Generic ACL support for in-memory filesystems. |
f0c8bd164 [PATCH] Generic i... |
7 8 9 |
*/ #include <linux/sched.h> |
5a0e3ad6a include cleanup: ... |
10 |
#include <linux/gfp.h> |
f0c8bd164 [PATCH] Generic i... |
11 12 |
#include <linux/fs.h> #include <linux/generic_acl.h> |
1c7c474c3 make generic_acl ... |
13 14 |
#include <linux/posix_acl.h> #include <linux/posix_acl_xattr.h> |
f0c8bd164 [PATCH] Generic i... |
15 |
|
1c7c474c3 make generic_acl ... |
16 17 18 19 |
static size_t generic_acl_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) |
f0c8bd164 [PATCH] Generic i... |
20 21 |
{ struct posix_acl *acl; |
1c7c474c3 make generic_acl ... |
22 |
const char *xname; |
f0c8bd164 [PATCH] Generic i... |
23 |
size_t size; |
1c7c474c3 make generic_acl ... |
24 |
acl = get_cached_acl(dentry->d_inode, type); |
f0c8bd164 [PATCH] Generic i... |
25 26 27 |
if (!acl) return 0; posix_acl_release(acl); |
1c7c474c3 make generic_acl ... |
28 29 30 31 32 33 34 35 36 |
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; |
f0c8bd164 [PATCH] Generic i... |
37 |
} |
1c7c474c3 make generic_acl ... |
38 |
size = strlen(xname) + 1; |
f0c8bd164 [PATCH] Generic i... |
39 |
if (list && size <= list_size) |
1c7c474c3 make generic_acl ... |
40 |
memcpy(list, xname, size); |
f0c8bd164 [PATCH] Generic i... |
41 42 |
return size; } |
1c7c474c3 make generic_acl ... |
43 44 45 |
static int generic_acl_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) |
f0c8bd164 [PATCH] Generic i... |
46 47 48 |
{ struct posix_acl *acl; int error; |
1c7c474c3 make generic_acl ... |
49 50 51 52 |
if (strcmp(name, "") != 0) return -EINVAL; acl = get_cached_acl(dentry->d_inode, type); |
f0c8bd164 [PATCH] Generic i... |
53 54 55 56 57 58 59 |
if (!acl) return -ENODATA; error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); return error; } |
1c7c474c3 make generic_acl ... |
60 61 62 |
static int generic_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) |
f0c8bd164 [PATCH] Generic i... |
63 |
{ |
1c7c474c3 make generic_acl ... |
64 |
struct inode *inode = dentry->d_inode; |
f0c8bd164 [PATCH] Generic i... |
65 66 |
struct posix_acl *acl = NULL; int error; |
1c7c474c3 make generic_acl ... |
67 68 |
if (strcmp(name, "") != 0) return -EINVAL; |
f0c8bd164 [PATCH] Generic i... |
69 70 |
if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; |
2e1496707 userns: rename is... |
71 |
if (!inode_owner_or_capable(inode)) |
f0c8bd164 [PATCH] Generic i... |
72 73 74 75 76 77 78 79 80 81 82 83 |
return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) return PTR_ERR(acl); } if (acl) { mode_t mode; error = posix_acl_valid(acl); if (error) goto failed; |
1c7c474c3 make generic_acl ... |
84 85 86 87 88 89 90 |
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; |
dad5eb6da vfs: update ctime... |
91 |
inode->i_ctime = CURRENT_TIME; |
1c7c474c3 make generic_acl ... |
92 93 94 95 96 97 98 99 100 101 102 |
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; |
f0c8bd164 [PATCH] Generic i... |
103 104 |
} } |
1c7c474c3 make generic_acl ... |
105 |
set_cached_acl(inode, type, acl); |
f0c8bd164 [PATCH] Generic i... |
106 107 108 109 110 111 112 113 |
error = 0; failed: posix_acl_release(acl); return error; } /** * generic_acl_init - Take care of acl inheritance at @inode create time |
f0c8bd164 [PATCH] Generic i... |
114 115 116 117 118 |
* * Files created inside a directory with a default ACL inherit the * directory's default ACL. */ int |
1c7c474c3 make generic_acl ... |
119 |
generic_acl_init(struct inode *inode, struct inode *dir) |
f0c8bd164 [PATCH] Generic i... |
120 121 122 123 |
{ struct posix_acl *acl = NULL; mode_t mode = inode->i_mode; int error; |
ce3b0f8d5 New helper - curr... |
124 |
inode->i_mode = mode & ~current_umask(); |
f0c8bd164 [PATCH] Generic i... |
125 |
if (!S_ISLNK(inode->i_mode)) |
1c7c474c3 make generic_acl ... |
126 |
acl = get_cached_acl(dir, ACL_TYPE_DEFAULT); |
f0c8bd164 [PATCH] Generic i... |
127 128 129 130 131 132 133 134 |
if (acl) { struct posix_acl *clone; if (S_ISDIR(inode->i_mode)) { clone = posix_acl_clone(acl, GFP_KERNEL); error = -ENOMEM; if (!clone) goto cleanup; |
1c7c474c3 make generic_acl ... |
135 |
set_cached_acl(inode, ACL_TYPE_DEFAULT, clone); |
f0c8bd164 [PATCH] Generic i... |
136 137 138 139 140 141 142 143 144 145 |
posix_acl_release(clone); } clone = posix_acl_clone(acl, GFP_KERNEL); error = -ENOMEM; if (!clone) goto cleanup; error = posix_acl_create_masq(clone, &mode); if (error >= 0) { inode->i_mode = mode; if (error > 0) |
1c7c474c3 make generic_acl ... |
146 |
set_cached_acl(inode, ACL_TYPE_ACCESS, clone); |
f0c8bd164 [PATCH] Generic i... |
147 148 149 150 151 152 153 154 155 156 157 158 |
} posix_acl_release(clone); } error = 0; cleanup: posix_acl_release(acl); return error; } /** * generic_acl_chmod - change the access acl of @inode upon chmod() |
f0c8bd164 [PATCH] Generic i... |
159 160 161 162 163 |
* * A chmod also changes the permissions of the owner, group/mask, and * other ACL entries. */ int |
1c7c474c3 make generic_acl ... |
164 |
generic_acl_chmod(struct inode *inode) |
f0c8bd164 [PATCH] Generic i... |
165 166 167 168 169 170 |
{ struct posix_acl *acl, *clone; int error = 0; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; |
1c7c474c3 make generic_acl ... |
171 |
acl = get_cached_acl(inode, ACL_TYPE_ACCESS); |
f0c8bd164 [PATCH] Generic i... |
172 173 174 175 176 177 178 |
if (acl) { clone = posix_acl_clone(acl, GFP_KERNEL); posix_acl_release(acl); if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) |
1c7c474c3 make generic_acl ... |
179 |
set_cached_acl(inode, ACL_TYPE_ACCESS, clone); |
f0c8bd164 [PATCH] Generic i... |
180 181 182 183 |
posix_acl_release(clone); } return error; } |
1c7c474c3 make generic_acl ... |
184 185 |
int |
b74c79e99 fs: provide rcu-w... |
186 |
generic_check_acl(struct inode *inode, int mask, unsigned int flags) |
1c7c474c3 make generic_acl ... |
187 |
{ |
1e1743ebe fs: provide simpl... |
188 189 190 191 192 193 194 195 196 197 198 199 |
if (flags & IPERM_FLAG_RCU) { if (!negative_cached_acl(inode, ACL_TYPE_ACCESS)) return -ECHILD; } else { struct posix_acl *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; } |
1c7c474c3 make generic_acl ... |
200 201 202 |
} return -EAGAIN; } |
bb4354538 fs: xattr_handler... |
203 |
const struct xattr_handler generic_acl_access_handler = { |
1c7c474c3 make generic_acl ... |
204 205 206 207 208 209 |
.prefix = POSIX_ACL_XATTR_ACCESS, .flags = ACL_TYPE_ACCESS, .list = generic_acl_list, .get = generic_acl_get, .set = generic_acl_set, }; |
bb4354538 fs: xattr_handler... |
210 |
const struct xattr_handler generic_acl_default_handler = { |
1c7c474c3 make generic_acl ... |
211 212 213 214 215 216 |
.prefix = POSIX_ACL_XATTR_DEFAULT, .flags = ACL_TYPE_DEFAULT, .list = generic_acl_list, .get = generic_acl_get, .set = generic_acl_set, }; |