Blame view
fs/gfs2/acl.c
6.42 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 |
|
479c427dd GFS2: Clean up ACLs |
41 42 43 44 45 46 |
static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) { struct posix_acl *acl; const char *name; char *data; int len; |
40b78a322 GFS2: Clean up of... |
47 |
|
3767ac21f GFS2: Move di_eat... |
48 |
if (!ip->i_eattr) |
479c427dd GFS2: Clean up ACLs |
49 |
return NULL; |
b3b94faa5 [GFS2] The core o... |
50 |
|
106381bfb GFS2: Add cached ... |
51 52 53 |
acl = get_cached_acl(&ip->i_inode, type); if (acl != ACL_NOT_CACHED) return acl; |
479c427dd GFS2: Clean up ACLs |
54 55 56 |
name = gfs2_acl_name(type); if (name == NULL) return ERR_PTR(-EINVAL); |
b3b94faa5 [GFS2] The core o... |
57 |
|
479c427dd GFS2: Clean up ACLs |
58 59 60 61 62 |
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... |
63 |
|
479c427dd GFS2: Clean up ACLs |
64 65 66 |
acl = posix_acl_from_xattr(data, len); kfree(data); return acl; |
b3b94faa5 [GFS2] The core o... |
67 |
} |
4e34e719e fs: take the ACL ... |
68 |
struct posix_acl *gfs2_get_acl(struct inode *inode, int type) |
b3b94faa5 [GFS2] The core o... |
69 |
{ |
4e34e719e fs: take the ACL ... |
70 |
return gfs2_acl_get(GFS2_I(inode), type); |
b3b94faa5 [GFS2] The core o... |
71 |
} |
d3fb61207 switch posix_acl_... |
72 |
static int gfs2_set_mode(struct inode *inode, umode_t mode) |
b3b94faa5 [GFS2] The core o... |
73 |
{ |
69dca4246 GFS2: Use gfs2_se... |
74 |
int error = 0; |
b3b94faa5 [GFS2] The core o... |
75 |
|
69dca4246 GFS2: Use gfs2_se... |
76 77 |
if (mode != inode->i_mode) { struct iattr iattr; |
b3b94faa5 [GFS2] The core o... |
78 |
|
69dca4246 GFS2: Use gfs2_se... |
79 80 |
iattr.ia_valid = ATTR_MODE; iattr.ia_mode = mode; |
b3b94faa5 [GFS2] The core o... |
81 |
|
69dca4246 GFS2: Use gfs2_se... |
82 83 |
error = gfs2_setattr_simple(GFS2_I(inode), &iattr); } |
b3b94faa5 [GFS2] The core o... |
84 |
|
69dca4246 GFS2: Use gfs2_se... |
85 |
return error; |
b3b94faa5 [GFS2] The core o... |
86 |
} |
479c427dd GFS2: Clean up ACLs |
87 |
static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) |
b3b94faa5 [GFS2] The core o... |
88 |
{ |
b3b94faa5 [GFS2] The core o... |
89 |
int error; |
479c427dd GFS2: Clean up ACLs |
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
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... |
104 |
error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); |
106381bfb GFS2: Add cached ... |
105 106 |
if (!error) set_cached_acl(inode, type, acl); |
479c427dd GFS2: Clean up ACLs |
107 108 109 110 111 112 113 114 |
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... |
115 |
struct posix_acl *acl; |
d3fb61207 switch posix_acl_... |
116 |
umode_t mode = inode->i_mode; |
479c427dd GFS2: Clean up ACLs |
117 |
int error = 0; |
b3b94faa5 [GFS2] The core o... |
118 119 120 |
if (!sdp->sd_args.ar_posix_acl) return 0; |
479c427dd GFS2: Clean up ACLs |
121 |
if (S_ISLNK(inode->i_mode)) |
b3b94faa5 [GFS2] The core o... |
122 |
return 0; |
479c427dd GFS2: Clean up ACLs |
123 124 125 |
acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); if (IS_ERR(acl)) return PTR_ERR(acl); |
b3b94faa5 [GFS2] The core o... |
126 |
if (!acl) { |
ce3b0f8d5 New helper - curr... |
127 |
mode &= ~current_umask(); |
479c427dd GFS2: Clean up ACLs |
128 129 |
if (mode != inode->i_mode) error = gfs2_set_mode(inode, mode); |
b3b94faa5 [GFS2] The core o... |
130 131 |
return error; } |
479c427dd GFS2: Clean up ACLs |
132 133 134 135 136 |
if (S_ISDIR(inode->i_mode)) { error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); if (error) goto out; } |
826cae2f2 kill boilerplates... |
137 |
error = posix_acl_create(&acl, GFP_NOFS, &mode); |
b3b94faa5 [GFS2] The core o... |
138 |
if (error < 0) |
826cae2f2 kill boilerplates... |
139 |
return error; |
40b78a322 GFS2: Clean up of... |
140 141 |
if (error == 0) goto munge; |
b3b94faa5 [GFS2] The core o... |
142 |
|
479c427dd GFS2: Clean up ACLs |
143 |
error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); |
40b78a322 GFS2: Clean up of... |
144 145 146 |
if (error) goto out; munge: |
479c427dd GFS2: Clean up ACLs |
147 |
error = gfs2_set_mode(inode, mode); |
a91ea69ff [GFS2] Align all ... |
148 |
out: |
b3b94faa5 [GFS2] The core o... |
149 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
150 151 152 153 154 |
return error; } int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) { |
bc26ab5f6 kill boilerplate ... |
155 |
struct posix_acl *acl; |
b3b94faa5 [GFS2] The core o... |
156 157 158 |
char *data; unsigned int len; int error; |
479c427dd GFS2: Clean up ACLs |
159 160 161 |
acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); if (IS_ERR(acl)) return PTR_ERR(acl); |
b3b94faa5 [GFS2] The core o... |
162 163 |
if (!acl) return gfs2_setattr_simple(ip, attr); |
bc26ab5f6 kill boilerplate ... |
164 165 166 167 168 169 |
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... |
170 |
error = -ENOMEM; |
bc26ab5f6 kill boilerplate ... |
171 |
if (data == NULL) |
b3b94faa5 [GFS2] The core o... |
172 |
goto out; |
bc26ab5f6 kill boilerplate ... |
173 174 175 176 |
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... |
177 |
|
a91ea69ff [GFS2] Align all ... |
178 |
out: |
b3b94faa5 [GFS2] The core o... |
179 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
180 181 |
return error; } |
2646a1f61 GFS2: Fix up syst... |
182 183 184 185 186 187 188 189 |
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... |
190 191 |
static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int xtype) |
2646a1f61 GFS2: Fix up syst... |
192 |
{ |
431547b3c sanitize xattr ha... |
193 |
struct inode *inode = dentry->d_inode; |
f72f2d2e2 GFS2: Don't "get"... |
194 |
struct gfs2_sbd *sdp = GFS2_SB(inode); |
106381bfb GFS2: Add cached ... |
195 |
struct posix_acl *acl; |
2646a1f61 GFS2: Fix up syst... |
196 |
int type; |
106381bfb GFS2: Add cached ... |
197 |
int error; |
2646a1f61 GFS2: Fix up syst... |
198 |
|
f72f2d2e2 GFS2: Don't "get"... |
199 200 |
if (!sdp->sd_args.ar_posix_acl) return -EOPNOTSUPP; |
2646a1f61 GFS2: Fix up syst... |
201 202 203 |
type = gfs2_acl_type(name); if (type < 0) return type; |
106381bfb GFS2: Add cached ... |
204 205 206 207 208 |
acl = gfs2_acl_get(GFS2_I(inode), type); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; |
2646a1f61 GFS2: Fix up syst... |
209 |
|
106381bfb GFS2: Add cached ... |
210 211 212 213 214 |
error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); return error; } |
2646a1f61 GFS2: Fix up syst... |
215 |
|
431547b3c sanitize xattr ha... |
216 217 218 |
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... |
219 |
{ |
431547b3c sanitize xattr ha... |
220 |
struct inode *inode = dentry->d_inode; |
2646a1f61 GFS2: Fix up syst... |
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 264 |
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_... |
265 |
umode_t mode = inode->i_mode; |
2646a1f61 GFS2: Fix up syst... |
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
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... |
282 |
error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); |
106381bfb GFS2: Add cached ... |
283 284 285 286 287 288 |
if (!error) { if (acl) set_cached_acl(inode, type, acl); else forget_cached_acl(inode, type); } |
2646a1f61 GFS2: Fix up syst... |
289 290 291 292 293 |
out_release: posix_acl_release(acl); out: return error; } |
b7bb0a129 gfs: constify xat... |
294 |
const struct xattr_handler gfs2_xattr_system_handler = { |
2646a1f61 GFS2: Fix up syst... |
295 |
.prefix = XATTR_SYSTEM_PREFIX, |
431547b3c sanitize xattr ha... |
296 |
.flags = GFS2_EATYPE_SYS, |
2646a1f61 GFS2: Fix up syst... |
297 298 299 |
.get = gfs2_xattr_system_get, .set = gfs2_xattr_system_set, }; |