Blame view
fs/gfs2/acl.c
5.54 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 15 16 |
*/ #include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> #include <linux/posix_acl.h> #include <linux/posix_acl_xattr.h> |
5c676f6d3 [GFS2] Macros rem... |
17 |
#include <linux/gfs2_ondisk.h> |
b3b94faa5 [GFS2] The core o... |
18 19 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
20 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
21 |
#include "acl.h" |
307cf6e63 GFS2: Rename eatt... |
22 |
#include "xattr.h" |
b3b94faa5 [GFS2] The core o... |
23 24 25 26 |
#include "glock.h" #include "inode.h" #include "meta_io.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
27 |
#include "util.h" |
b3b94faa5 [GFS2] The core o... |
28 29 30 31 32 |
#define ACL_ACCESS 1 #define ACL_DEFAULT 0 int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, |
40b78a322 GFS2: Clean up of... |
33 |
struct gfs2_ea_request *er, int *remove, mode_t *mode) |
b3b94faa5 [GFS2] The core o... |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
{ struct posix_acl *acl; int error; error = gfs2_acl_validate_remove(ip, access); if (error) return error; if (!er->er_data) return -EINVAL; acl = posix_acl_from_xattr(er->er_data, er->er_data_len); if (IS_ERR(acl)) return PTR_ERR(acl); if (!acl) { *remove = 1; return 0; } error = posix_acl_valid(acl); if (error) goto out; if (access) { error = posix_acl_equiv_mode(acl, mode); if (!error) *remove = 1; else if (error > 0) error = 0; } |
a91ea69ff [GFS2] Align all ... |
64 |
out: |
b3b94faa5 [GFS2] The core o... |
65 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
66 67 68 69 70 |
return error; } int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access) { |
feaa7bba0 [GFS2] Fix unlink... |
71 |
if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl) |
b3b94faa5 [GFS2] The core o... |
72 |
return -EOPNOTSUPP; |
3bd858ab1 Introduce is_owne... |
73 |
if (!is_owner_or_cap(&ip->i_inode)) |
b3b94faa5 [GFS2] The core o... |
74 |
return -EPERM; |
b60623c23 [GFS2] Shrink gfs... |
75 |
if (S_ISLNK(ip->i_inode.i_mode)) |
b3b94faa5 [GFS2] The core o... |
76 |
return -EOPNOTSUPP; |
b60623c23 [GFS2] Shrink gfs... |
77 |
if (!access && !S_ISDIR(ip->i_inode.i_mode)) |
b3b94faa5 [GFS2] The core o... |
78 79 80 81 |
return -EACCES; return 0; } |
40b78a322 GFS2: Clean up of... |
82 83 84 |
static int acl_get(struct gfs2_inode *ip, const char *name, struct posix_acl **acl, struct gfs2_ea_location *el, char **datap, unsigned int *lenp) |
b3b94faa5 [GFS2] The core o... |
85 |
{ |
40b78a322 GFS2: Clean up of... |
86 87 |
char *data; unsigned int len; |
b3b94faa5 [GFS2] The core o... |
88 |
int error; |
40b78a322 GFS2: Clean up of... |
89 |
el->el_bh = NULL; |
3767ac21f GFS2: Move di_eat... |
90 |
if (!ip->i_eattr) |
b3b94faa5 [GFS2] The core o... |
91 |
return 0; |
40b78a322 GFS2: Clean up of... |
92 |
error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, el); |
b3b94faa5 [GFS2] The core o... |
93 94 95 96 97 98 |
if (error) return error; if (!el->el_ea) return 0; if (!GFS2_EA_DATA_LEN(el->el_ea)) goto out; |
40b78a322 GFS2: Clean up of... |
99 100 |
len = GFS2_EA_DATA_LEN(el->el_ea); data = kmalloc(len, GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
101 |
error = -ENOMEM; |
40b78a322 GFS2: Clean up of... |
102 |
if (!data) |
b3b94faa5 [GFS2] The core o... |
103 |
goto out; |
40b78a322 GFS2: Clean up of... |
104 105 |
error = gfs2_ea_get_copy(ip, el, data, len); if (error < 0) |
b3b94faa5 [GFS2] The core o... |
106 |
goto out_kfree; |
40b78a322 GFS2: Clean up of... |
107 |
error = 0; |
b3b94faa5 [GFS2] The core o... |
108 109 |
if (acl) { |
40b78a322 GFS2: Clean up of... |
110 |
*acl = posix_acl_from_xattr(data, len); |
b3b94faa5 [GFS2] The core o... |
111 112 113 |
if (IS_ERR(*acl)) error = PTR_ERR(*acl); } |
a91ea69ff [GFS2] Align all ... |
114 |
out_kfree: |
40b78a322 GFS2: Clean up of... |
115 116 117 118 119 |
if (error || !datap) { kfree(data); } else { *datap = data; *lenp = len; |
b3b94faa5 [GFS2] The core o... |
120 |
} |
a91ea69ff [GFS2] Align all ... |
121 |
out: |
b3b94faa5 [GFS2] The core o... |
122 123 124 125 |
return error; } /** |
77386e1f6 [GFS2] Remove gfs... |
126 |
* gfs2_check_acl - Check an ACL to see if we're allowed to do something |
b3b94faa5 [GFS2] The core o... |
127 128 129 130 131 |
* @inode: the file we want to do something to * @mask: what we want to do * * Returns: errno */ |
77386e1f6 [GFS2] Remove gfs... |
132 |
int gfs2_check_acl(struct inode *inode, int mask) |
b3b94faa5 [GFS2] The core o... |
133 |
{ |
40b78a322 GFS2: Clean up of... |
134 |
struct gfs2_ea_location el; |
b3b94faa5 [GFS2] The core o... |
135 136 |
struct posix_acl *acl = NULL; int error; |
40b78a322 GFS2: Clean up of... |
137 138 |
error = acl_get(GFS2_I(inode), GFS2_POSIX_ACL_ACCESS, &acl, &el, NULL, NULL); brelse(el.el_bh); |
b3b94faa5 [GFS2] The core o... |
139 140 141 142 143 144 145 146 147 148 149 |
if (error) return error; if (acl) { error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); return error; } return -EAGAIN; } |
b3b94faa5 [GFS2] The core o... |
150 151 |
static int munge_mode(struct gfs2_inode *ip, mode_t mode) { |
feaa7bba0 [GFS2] Fix unlink... |
152 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
b3b94faa5 [GFS2] The core o... |
153 154 155 156 157 158 159 160 161 162 |
struct buffer_head *dibh; int error; error = gfs2_trans_begin(sdp, RES_DINODE, 0); if (error) return error; error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { gfs2_assert_withdraw(sdp, |
b60623c23 [GFS2] Shrink gfs... |
163 164 |
(ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT)); ip->i_inode.i_mode = mode; |
d4e9c4c3b [GFS2] Add an add... |
165 |
gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
539e5d6b7 [GFS2] Change arg... |
166 |
gfs2_dinode_out(ip, dibh->b_data); |
b3b94faa5 [GFS2] The core o... |
167 168 169 170 171 172 173 174 175 176 |
brelse(dibh); } gfs2_trans_end(sdp); return 0; } int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) { |
40b78a322 GFS2: Clean up of... |
177 |
struct gfs2_ea_location el; |
feaa7bba0 [GFS2] Fix unlink... |
178 |
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
b3b94faa5 [GFS2] The core o... |
179 |
struct posix_acl *acl = NULL, *clone; |
b60623c23 [GFS2] Shrink gfs... |
180 |
mode_t mode = ip->i_inode.i_mode; |
40b78a322 GFS2: Clean up of... |
181 182 |
char *data = NULL; unsigned int len; |
b3b94faa5 [GFS2] The core o... |
183 184 185 186 |
int error; if (!sdp->sd_args.ar_posix_acl) return 0; |
b60623c23 [GFS2] Shrink gfs... |
187 |
if (S_ISLNK(ip->i_inode.i_mode)) |
b3b94faa5 [GFS2] The core o... |
188 |
return 0; |
40b78a322 GFS2: Clean up of... |
189 190 |
error = acl_get(dip, GFS2_POSIX_ACL_DEFAULT, &acl, &el, &data, &len); brelse(el.el_bh); |
b3b94faa5 [GFS2] The core o... |
191 192 193 |
if (error) return error; if (!acl) { |
ce3b0f8d5 New helper - curr... |
194 |
mode &= ~current_umask(); |
b60623c23 [GFS2] Shrink gfs... |
195 |
if (mode != ip->i_inode.i_mode) |
b3b94faa5 [GFS2] The core o... |
196 197 198 |
error = munge_mode(ip, mode); return error; } |
16c5f06f1 [GFS2] fix GFP_KE... |
199 |
clone = posix_acl_clone(acl, GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
200 201 202 203 204 |
error = -ENOMEM; if (!clone) goto out; posix_acl_release(acl); acl = clone; |
b60623c23 [GFS2] Shrink gfs... |
205 |
if (S_ISDIR(ip->i_inode.i_mode)) { |
40b78a322 GFS2: Clean up of... |
206 207 |
error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_DEFAULT, data, len, 0); |
b3b94faa5 [GFS2] The core o... |
208 209 210 211 212 213 214 |
if (error) goto out; } error = posix_acl_create_masq(acl, &mode); if (error < 0) goto out; |
40b78a322 GFS2: Clean up of... |
215 216 |
if (error == 0) goto munge; |
b3b94faa5 [GFS2] The core o... |
217 |
|
40b78a322 GFS2: Clean up of... |
218 219 220 221 222 223 224 |
posix_acl_to_xattr(acl, data, len); error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, data, len, 0); if (error) goto out; munge: error = munge_mode(ip, mode); |
a91ea69ff [GFS2] Align all ... |
225 |
out: |
b3b94faa5 [GFS2] The core o... |
226 |
posix_acl_release(acl); |
40b78a322 GFS2: Clean up of... |
227 |
kfree(data); |
b3b94faa5 [GFS2] The core o... |
228 229 230 231 232 233 234 235 236 237 |
return error; } int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) { struct posix_acl *acl = NULL, *clone; struct gfs2_ea_location el; char *data; unsigned int len; int error; |
40b78a322 GFS2: Clean up of... |
238 |
error = acl_get(ip, GFS2_POSIX_ACL_ACCESS, &acl, &el, &data, &len); |
b3b94faa5 [GFS2] The core o... |
239 |
if (error) |
40b78a322 GFS2: Clean up of... |
240 |
goto out_brelse; |
b3b94faa5 [GFS2] The core o... |
241 242 |
if (!acl) return gfs2_setattr_simple(ip, attr); |
16c5f06f1 [GFS2] fix GFP_KE... |
243 |
clone = posix_acl_clone(acl, GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
244 245 246 247 248 249 250 251 252 253 254 |
error = -ENOMEM; if (!clone) goto out; posix_acl_release(acl); acl = clone; error = posix_acl_chmod_masq(acl, attr->ia_mode); if (!error) { posix_acl_to_xattr(acl, data, len); error = gfs2_ea_acl_chmod(ip, &el, attr, data); } |
a91ea69ff [GFS2] Align all ... |
255 |
out: |
b3b94faa5 [GFS2] The core o... |
256 |
posix_acl_release(acl); |
b3b94faa5 [GFS2] The core o... |
257 |
kfree(data); |
40b78a322 GFS2: Clean up of... |
258 259 |
out_brelse: brelse(el.el_bh); |
b3b94faa5 [GFS2] The core o... |
260 261 |
return error; } |