Blame view
fs/gfs2/acl.c
6.39 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103 [GFS2] Update cop... |
3 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 9 10 11 12 13 14 |
*/ #include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
2646a1f61 GFS2: Fix up syst... |
15 |
#include <linux/xattr.h> |
b3b94faa5 [GFS2] The core o... |
16 17 |
#include <linux/posix_acl.h> #include <linux/posix_acl_xattr.h> |
5c676f6d3 [GFS2] Macros rem... |
18 |
#include <linux/gfs2_ondisk.h> |
b3b94faa5 [GFS2] The core o... |
19 20 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
21 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
22 |
#include "acl.h" |
307cf6e63 GFS2: Rename eatt... |
23 |
#include "xattr.h" |
b3b94faa5 [GFS2] The core o... |
24 25 26 27 |
#include "glock.h" #include "inode.h" #include "meta_io.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
28 |
#include "util.h" |
b3b94faa5 [GFS2] The core o... |
29 |
|
479c427dd GFS2: Clean up ACLs |
30 |
static const char *gfs2_acl_name(int type) |
b3b94faa5 [GFS2] The core o... |
31 |
{ |
479c427dd GFS2: Clean up ACLs |
32 33 34 35 36 37 38 39 |
switch (type) { case ACL_TYPE_ACCESS: return GFS2_POSIX_ACL_ACCESS; case ACL_TYPE_DEFAULT: return GFS2_POSIX_ACL_DEFAULT; } return NULL; } |
b3b94faa5 [GFS2] The core o... |
40 |
|
018a01cd2 GFS2: We only nee... |
41 |
struct posix_acl *gfs2_get_acl(struct inode *inode, int type) |
479c427dd GFS2: Clean up ACLs |
42 |
{ |
018a01cd2 GFS2: We only nee... |
43 |
struct gfs2_inode *ip = GFS2_I(inode); |
479c427dd GFS2: Clean up ACLs |
44 45 46 47 |
struct posix_acl *acl; const char *name; char *data; int len; |
40b78a322 GFS2: Clean up of... |
48 |
|
3767ac21f GFS2: Move di_eat... |
49 |
if (!ip->i_eattr) |
479c427dd GFS2: Clean up ACLs |
50 |
return NULL; |
b3b94faa5 [GFS2] The core o... |
51 |
|
106381bfb GFS2: Add cached ... |
52 53 54 |
acl = get_cached_acl(&ip->i_inode, type); if (acl != ACL_NOT_CACHED) return acl; |
479c427dd GFS2: Clean up ACLs |
55 56 57 |
name = gfs2_acl_name(type); if (name == NULL) return ERR_PTR(-EINVAL); |
b3b94faa5 [GFS2] The core o... |
58 |
|
479c427dd GFS2: Clean up ACLs |
59 60 61 62 63 |
len = gfs2_xattr_acl_get(ip, name, &data); if (len < 0) return ERR_PTR(len); if (len == 0) return NULL; |
b3b94faa5 [GFS2] The core o... |
64 |
|
479c427dd GFS2: Clean up ACLs |
65 66 67 |
acl = posix_acl_from_xattr(data, len); kfree(data); return acl; |
b3b94faa5 [GFS2] The core o... |
68 |
} |
d3fb61207 switch posix_acl_... |
69 |
static int gfs2_set_mode(struct inode *inode, umode_t mode) |
b3b94faa5 [GFS2] The core o... |
70 |
{ |
69dca4246 GFS2: Use gfs2_se... |
71 |
int error = 0; |
b3b94faa5 [GFS2] The core o... |
72 |
|
69dca4246 GFS2: Use gfs2_se... |
73 74 |
if (mode != inode->i_mode) { struct iattr iattr; |
b3b94faa5 [GFS2] The core o... |
75 |
|
69dca4246 GFS2: Use gfs2_se... |
76 77 |
iattr.ia_valid = ATTR_MODE; iattr.ia_mode = mode; |
b3b94faa5 [GFS2] The core o... |
78 |
|
ab9bbda02 GFS2: Use ->dirty... |
79 |
error = gfs2_setattr_simple(inode, &iattr); |
69dca4246 GFS2: Use gfs2_se... |
80 |
} |
b3b94faa5 [GFS2] The core o... |
81 |
|
69dca4246 GFS2: Use gfs2_se... |
82 |
return error; |
b3b94faa5 [GFS2] The core o... |
83 |
} |
479c427dd GFS2: Clean up ACLs |
84 |
static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) |
b3b94faa5 [GFS2] The core o... |
85 |
{ |
b3b94faa5 [GFS2] The core o... |
86 |
int error; |
479c427dd GFS2: Clean up ACLs |
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
int len; char *data; const char *name = gfs2_acl_name(type); BUG_ON(name == NULL); len = posix_acl_to_xattr(acl, NULL, 0); if (len == 0) return 0; data = kmalloc(len, GFP_NOFS); if (data == NULL) return -ENOMEM; error = posix_acl_to_xattr(acl, data, len); if (error < 0) goto out; |
431547b3c sanitize xattr ha... |
101 |
error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); |
106381bfb GFS2: Add cached ... |
102 103 |
if (!error) set_cached_acl(inode, type, acl); |
479c427dd GFS2: Clean up ACLs |
104 105 106 107 108 109 110 111 |
out: kfree(data); return error; } int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
826cae2f2 kill boilerplates... |
112 |
struct posix_acl *acl; |
d3fb61207 switch posix_acl_... |
113 |
umode_t mode = inode->i_mode; |
479c427dd GFS2: Clean up ACLs |
114 |
int error = 0; |
b3b94faa5 [GFS2] The core o... |
115 116 117 |
if (!sdp->sd_args.ar_posix_acl) return 0; |
479c427dd GFS2: Clean up ACLs |
118 |
if (S_ISLNK(inode->i_mode)) |
b3b94faa5 [GFS2] The core o... |
119 |
return 0; |
018a01cd2 GFS2: We only nee... |
120 |
acl = gfs2_get_acl(&dip->i_inode, ACL_TYPE_DEFAULT); |
479c427dd GFS2: Clean up ACLs |
121 122 |
if (IS_ERR(acl)) return PTR_ERR(acl); |
b3b94faa5 [GFS2] The core o... |
123 |
if (!acl) { |
ce3b0f8d5 New helper - curr... |
124 |
mode &= ~current_umask(); |
479c427dd GFS2: Clean up ACLs |
125 126 |
if (mode != inode->i_mode) error = gfs2_set_mode(inode, mode); |
b3b94faa5 [GFS2] The core o... |
127 128 |
return error; } |
479c427dd GFS2: Clean up ACLs |
129 130 131 132 133 |
if (S_ISDIR(inode->i_mode)) { error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); if (error) goto out; } |
826cae2f2 kill boilerplates... |
134 |
error = posix_acl_create(&acl, GFP_NOFS, &mode); |
b3b94faa5 [GFS2] The core o... |
135 |
if (error < 0) |
826cae2f2 kill boilerplates... |
136 |
return error; |
40b78a322 GFS2: Clean up of... |
137 138 |
if (error == 0) goto munge; |
b3b94faa5 [GFS2] The core o... |
139 |
|
479c427dd GFS2: Clean up ACLs |
140 |
error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); |
40b78a322 GFS2: Clean up of... |
141 142 143 |
if (error) goto out; munge: |
479c427dd GFS2: Clean up ACLs |
144 |
error = gfs2_set_mode(inode, mode); |
a91ea69ff [GFS2] Align all ... |
145 |
out: |
b3b94faa5 [GFS2] The core o... |
146 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
147 148 149 150 151 |
return error; } int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) { |
ab9bbda02 GFS2: Use ->dirty... |
152 |
struct inode *inode = &ip->i_inode; |
bc26ab5f6 kill boilerplate ... |
153 |
struct posix_acl *acl; |
b3b94faa5 [GFS2] The core o... |
154 155 156 |
char *data; unsigned int len; int error; |
018a01cd2 GFS2: We only nee... |
157 |
acl = gfs2_get_acl(&ip->i_inode, ACL_TYPE_ACCESS); |
479c427dd GFS2: Clean up ACLs |
158 159 |
if (IS_ERR(acl)) return PTR_ERR(acl); |
b3b94faa5 [GFS2] The core o... |
160 |
if (!acl) |
ab9bbda02 GFS2: Use ->dirty... |
161 |
return gfs2_setattr_simple(inode, attr); |
b3b94faa5 [GFS2] The core o... |
162 |
|
bc26ab5f6 kill boilerplate ... |
163 164 165 166 167 168 |
error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode); if (error) return error; len = posix_acl_to_xattr(acl, NULL, 0); data = kmalloc(len, GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
169 |
error = -ENOMEM; |
bc26ab5f6 kill boilerplate ... |
170 |
if (data == NULL) |
b3b94faa5 [GFS2] The core o... |
171 |
goto out; |
bc26ab5f6 kill boilerplate ... |
172 173 174 175 |
posix_acl_to_xattr(acl, data, len); error = gfs2_xattr_acl_chmod(ip, attr, data); kfree(data); set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl); |
b3b94faa5 [GFS2] The core o... |
176 |
|
a91ea69ff [GFS2] Align all ... |
177 |
out: |
b3b94faa5 [GFS2] The core o... |
178 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
179 180 |
return error; } |
2646a1f61 GFS2: Fix up syst... |
181 182 183 184 185 186 187 188 |
static int gfs2_acl_type(const char *name) { if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) return ACL_TYPE_ACCESS; if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) return ACL_TYPE_DEFAULT; return -EINVAL; } |
431547b3c sanitize xattr ha... |
189 190 |
static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int xtype) |
2646a1f61 GFS2: Fix up syst... |
191 |
{ |
431547b3c sanitize xattr ha... |
192 |
struct inode *inode = dentry->d_inode; |
f72f2d2e2 GFS2: Don't "get"... |
193 |
struct gfs2_sbd *sdp = GFS2_SB(inode); |
106381bfb GFS2: Add cached ... |
194 |
struct posix_acl *acl; |
2646a1f61 GFS2: Fix up syst... |
195 |
int type; |
106381bfb GFS2: Add cached ... |
196 |
int error; |
2646a1f61 GFS2: Fix up syst... |
197 |
|
f72f2d2e2 GFS2: Don't "get"... |
198 199 |
if (!sdp->sd_args.ar_posix_acl) return -EOPNOTSUPP; |
2646a1f61 GFS2: Fix up syst... |
200 201 202 |
type = gfs2_acl_type(name); if (type < 0) return type; |
018a01cd2 GFS2: We only nee... |
203 |
acl = gfs2_get_acl(inode, type); |
106381bfb GFS2: Add cached ... |
204 205 206 207 |
if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; |
2646a1f61 GFS2: Fix up syst... |
208 |
|
106381bfb GFS2: Add cached ... |
209 210 211 212 213 |
error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); return error; } |
2646a1f61 GFS2: Fix up syst... |
214 |
|
431547b3c sanitize xattr ha... |
215 216 217 |
static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int xtype) |
2646a1f61 GFS2: Fix up syst... |
218 |
{ |
431547b3c sanitize xattr ha... |
219 |
struct inode *inode = dentry->d_inode; |
2646a1f61 GFS2: Fix up syst... |
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
struct gfs2_sbd *sdp = GFS2_SB(inode); struct posix_acl *acl = NULL; int error = 0, type; if (!sdp->sd_args.ar_posix_acl) return -EOPNOTSUPP; type = gfs2_acl_type(name); if (type < 0) return type; if (flags & XATTR_CREATE) return -EINVAL; if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) return value ? -EACCES : 0; if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!value) goto set_acl; acl = posix_acl_from_xattr(value, size); if (!acl) { /* * acl_set_file(3) may request that we set default ACLs with * zero length -- defend (gracefully) against that here. */ goto out; } if (IS_ERR(acl)) { error = PTR_ERR(acl); goto out; } error = posix_acl_valid(acl); if (error) goto out_release; error = -EINVAL; if (acl->a_count > GFS2_ACL_MAX_ENTRIES) goto out_release; if (type == ACL_TYPE_ACCESS) { |
d6952123b switch posix_acl_... |
264 |
umode_t mode = inode->i_mode; |
2646a1f61 GFS2: Fix up syst... |
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
error = posix_acl_equiv_mode(acl, &mode); if (error <= 0) { posix_acl_release(acl); acl = NULL; if (error < 0) return error; } error = gfs2_set_mode(inode, mode); if (error) goto out_release; } set_acl: |
431547b3c sanitize xattr ha... |
281 |
error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); |
106381bfb GFS2: Add cached ... |
282 283 284 285 286 287 |
if (!error) { if (acl) set_cached_acl(inode, type, acl); else forget_cached_acl(inode, type); } |
2646a1f61 GFS2: Fix up syst... |
288 289 290 291 292 |
out_release: posix_acl_release(acl); out: return error; } |
b7bb0a129 gfs: constify xat... |
293 |
const struct xattr_handler gfs2_xattr_system_handler = { |
2646a1f61 GFS2: Fix up syst... |
294 |
.prefix = XATTR_SYSTEM_PREFIX, |
431547b3c sanitize xattr ha... |
295 |
.flags = GFS2_EATYPE_SYS, |
2646a1f61 GFS2: Fix up syst... |
296 297 298 |
.get = gfs2_xattr_system_get, .set = gfs2_xattr_system_set, }; |