1 /* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4 * 5 * This copyrighted material is made available to anyone wishing to use, 6 * modify, copy, or redistribute it subject to the terms and conditions 7 * of the GNU General Public License version 2. 8 */ 9 10 #include <linux/sched.h> 11 #include <linux/slab.h> 12 #include <linux/spinlock.h> 13 #include <linux/completion.h> 14 #include <linux/buffer_head.h> 15 #include <linux/xattr.h> 16 #include <linux/posix_acl.h> 17 #include <linux/posix_acl_xattr.h> 18 #include <linux/gfs2_ondisk.h> 19 20 #include "gfs2.h" 21 #include "incore.h" 22 #include "acl.h" 23 #include "xattr.h" 24 #include "glock.h" 25 #include "inode.h" 26 #include "meta_io.h" 27 #include "trans.h" 28 #include "util.h" 29 30 static const char *gfs2_acl_name(int type) 31 { 32 switch (type) { 33 case ACL_TYPE_ACCESS: 34 return GFS2_POSIX_ACL_ACCESS; 35 case ACL_TYPE_DEFAULT: 36 return GFS2_POSIX_ACL_DEFAULT; 37 } 38 return NULL; 39 } 40 41 static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) 42 { 43 struct posix_acl *acl; 44 const char *name; 45 char *data; 46 int len; 47 48 if (!ip->i_eattr) 49 return NULL; 50 51 acl = get_cached_acl(&ip->i_inode, type); 52 if (acl != ACL_NOT_CACHED) 53 return acl; 54 55 name = gfs2_acl_name(type); 56 if (name == NULL) 57 return ERR_PTR(-EINVAL); 58 59 len = gfs2_xattr_acl_get(ip, name, &data); 60 if (len < 0) 61 return ERR_PTR(len); 62 if (len == 0) 63 return NULL; 64 65 acl = posix_acl_from_xattr(data, len); 66 kfree(data); 67 return acl; 68 } 69 70 /** 71 * gfs2_check_acl - Check an ACL to see if we're allowed to do something 72 * @inode: the file we want to do something to 73 * @mask: what we want to do 74 * 75 * Returns: errno 76 */ 77 78 int gfs2_check_acl(struct inode *inode, int mask) 79 { 80 struct posix_acl *acl; 81 int error; 82 83 acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); 84 if (IS_ERR(acl)) 85 return PTR_ERR(acl); 86 87 if (acl) { 88 error = posix_acl_permission(inode, acl, mask); 89 posix_acl_release(acl); 90 return error; 91 } 92 93 return -EAGAIN; 94 } 95 96 static int gfs2_set_mode(struct inode *inode, mode_t mode) 97 { 98 int error = 0; 99 100 if (mode != inode->i_mode) { 101 struct iattr iattr; 102 103 iattr.ia_valid = ATTR_MODE; 104 iattr.ia_mode = mode; 105 106 error = gfs2_setattr_simple(GFS2_I(inode), &iattr); 107 } 108 109 return error; 110 } 111 112 static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) 113 { 114 int error; 115 int len; 116 char *data; 117 const char *name = gfs2_acl_name(type); 118 119 BUG_ON(name == NULL); 120 len = posix_acl_to_xattr(acl, NULL, 0); 121 if (len == 0) 122 return 0; 123 data = kmalloc(len, GFP_NOFS); 124 if (data == NULL) 125 return -ENOMEM; 126 error = posix_acl_to_xattr(acl, data, len); 127 if (error < 0) 128 goto out; 129 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 130 if (!error) 131 set_cached_acl(inode, type, acl); 132 out: 133 kfree(data); 134 return error; 135 } 136 137 int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode) 138 { 139 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 140 struct posix_acl *acl, *clone; 141 mode_t mode = inode->i_mode; 142 int error = 0; 143 144 if (!sdp->sd_args.ar_posix_acl) 145 return 0; 146 if (S_ISLNK(inode->i_mode)) 147 return 0; 148 149 acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); 150 if (IS_ERR(acl)) 151 return PTR_ERR(acl); 152 if (!acl) { 153 mode &= ~current_umask(); 154 if (mode != inode->i_mode) 155 error = gfs2_set_mode(inode, mode); 156 return error; 157 } 158 159 if (S_ISDIR(inode->i_mode)) { 160 error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); 161 if (error) 162 goto out; 163 } 164 165 clone = posix_acl_clone(acl, GFP_NOFS); 166 error = -ENOMEM; 167 if (!clone) 168 goto out; 169 posix_acl_release(acl); 170 acl = clone; 171 172 error = posix_acl_create_masq(acl, &mode); 173 if (error < 0) 174 goto out; 175 if (error == 0) 176 goto munge; 177 178 error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); 179 if (error) 180 goto out; 181 munge: 182 error = gfs2_set_mode(inode, mode); 183 out: 184 posix_acl_release(acl); 185 return error; 186 } 187 188 int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) 189 { 190 struct posix_acl *acl, *clone; 191 char *data; 192 unsigned int len; 193 int error; 194 195 acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); 196 if (IS_ERR(acl)) 197 return PTR_ERR(acl); 198 if (!acl) 199 return gfs2_setattr_simple(ip, attr); 200 201 clone = posix_acl_clone(acl, GFP_NOFS); 202 error = -ENOMEM; 203 if (!clone) 204 goto out; 205 posix_acl_release(acl); 206 acl = clone; 207 208 error = posix_acl_chmod_masq(acl, attr->ia_mode); 209 if (!error) { 210 len = posix_acl_to_xattr(acl, NULL, 0); 211 data = kmalloc(len, GFP_NOFS); 212 error = -ENOMEM; 213 if (data == NULL) 214 goto out; 215 posix_acl_to_xattr(acl, data, len); 216 error = gfs2_xattr_acl_chmod(ip, attr, data); 217 kfree(data); 218 set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl); 219 } 220 221 out: 222 posix_acl_release(acl); 223 return error; 224 } 225 226 static int gfs2_acl_type(const char *name) 227 { 228 if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) 229 return ACL_TYPE_ACCESS; 230 if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) 231 return ACL_TYPE_DEFAULT; 232 return -EINVAL; 233 } 234 235 static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, 236 void *buffer, size_t size, int xtype) 237 { 238 struct inode *inode = dentry->d_inode; 239 struct gfs2_sbd *sdp = GFS2_SB(inode); 240 struct posix_acl *acl; 241 int type; 242 int error; 243 244 if (!sdp->sd_args.ar_posix_acl) 245 return -EOPNOTSUPP; 246 247 type = gfs2_acl_type(name); 248 if (type < 0) 249 return type; 250 251 acl = gfs2_acl_get(GFS2_I(inode), type); 252 if (IS_ERR(acl)) 253 return PTR_ERR(acl); 254 if (acl == NULL) 255 return -ENODATA; 256 257 error = posix_acl_to_xattr(acl, buffer, size); 258 posix_acl_release(acl); 259 260 return error; 261 } 262 263 static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, 264 const void *value, size_t size, int flags, 265 int xtype) 266 { 267 struct inode *inode = dentry->d_inode; 268 struct gfs2_sbd *sdp = GFS2_SB(inode); 269 struct posix_acl *acl = NULL; 270 int error = 0, type; 271 272 if (!sdp->sd_args.ar_posix_acl) 273 return -EOPNOTSUPP; 274 275 type = gfs2_acl_type(name); 276 if (type < 0) 277 return type; 278 if (flags & XATTR_CREATE) 279 return -EINVAL; 280 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 281 return value ? -EACCES : 0; 282 if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) 283 return -EPERM; 284 if (S_ISLNK(inode->i_mode)) 285 return -EOPNOTSUPP; 286 287 if (!value) 288 goto set_acl; 289 290 acl = posix_acl_from_xattr(value, size); 291 if (!acl) { 292 /* 293 * acl_set_file(3) may request that we set default ACLs with 294 * zero length -- defend (gracefully) against that here. 295 */ 296 goto out; 297 } 298 if (IS_ERR(acl)) { 299 error = PTR_ERR(acl); 300 goto out; 301 } 302 303 error = posix_acl_valid(acl); 304 if (error) 305 goto out_release; 306 307 error = -EINVAL; 308 if (acl->a_count > GFS2_ACL_MAX_ENTRIES) 309 goto out_release; 310 311 if (type == ACL_TYPE_ACCESS) { 312 mode_t mode = inode->i_mode; 313 error = posix_acl_equiv_mode(acl, &mode); 314 315 if (error <= 0) { 316 posix_acl_release(acl); 317 acl = NULL; 318 319 if (error < 0) 320 return error; 321 } 322 323 error = gfs2_set_mode(inode, mode); 324 if (error) 325 goto out_release; 326 } 327 328 set_acl: 329 error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); 330 if (!error) { 331 if (acl) 332 set_cached_acl(inode, type, acl); 333 else 334 forget_cached_acl(inode, type); 335 } 336 out_release: 337 posix_acl_release(acl); 338 out: 339 return error; 340 } 341 342 const struct xattr_handler gfs2_xattr_system_handler = { 343 .prefix = XATTR_SYSTEM_PREFIX, 344 .flags = GFS2_EATYPE_SYS, 345 .get = gfs2_xattr_system_get, 346 .set = gfs2_xattr_system_set, 347 }; 348 349